This control was selected because an editable gridpanel control was required during a development yesterday. In addition, because the subject has a tree structure of 3-4 levels, you need to find a suitable treegridpanel.
I searched the internet for a long time before I found that in extjs3.0, ext. UX. maximgb. TG. the editorgridpanel class provides support for my needs. For a preliminary analysis, there are still some such problems. I am still using this control for development. If there is any new content that will be updated in a timely manner, you are welcome to study with me through e-mail. Most of my modifications are implemented through use without modifying the source code. In fact, you can modify the source code to encapsulate them by disabling specified row editing and statistics on non-leaf nodes, however, due to the end of project development next week, there is no time to complete it. I will consider encapsulating a new treegrid class to implement the following methods after the Project intercept, and hope to discuss it with you.
1. Parameters _ LFT and _ rgt do not know how to set them. Can they be used?
In fact, you do not need to set _ LFT and _ rgt. Many code on the Internet provides the following implementation:
VaR DATA = [
{"_ Id": 1, "_ parent": NULL, "_ Level": 1, "_ LFT": 1, "_ rgt": 98, "_ is_leaf": false, "item": "main business cost", "YN": 64.72 },
{"_ Id": 2, "_ parent": 1, "_ Level": 2, "_ LFT": 2, "_ rgt": 49, "_ is_leaf": True, "item": "network maintenance costs", "YN": 64.72}
];
VaR record = ext. Data. Record. Create ([
{Name: '_ id', type: 'int '},
{Name: '_ level', type: 'int '},
{Name: '_ LFT', type: 'int '},
{Name: '_ rgt', type: 'int '},
{Name: '_ is_leaf', type: 'bool '},
{Name: 'item '},
{Name: 'benbu ', type: 'float '}
]);
VaR store = new Ext. UX. maximgb. TG. nestedsetstore ({
Autoload: True,
Reader: New Ext. Data. jsonreader ({ID: '_ id'}, record ),
Proxy: New Ext. Data. memoryproxy (data)
});
Here, why do we need to set _ LFT and _ rgt because Ext. UX. maximgb. TG. for the needs of nestedsetstore, you can use treegrid. the source code of the JS file can be analyzed. In this store, the tree structure uses an infinite Classification Algorithm Based on left and right values. However, in our use, generating this parameter for this JSON object is quite troublesome. At least we cannot find a solution. While studying this piece of code, I also found. UX. maximgb. TG. the ext. UX. maximgb. TG. the most important thing about adjacencyliststore is that the parameters required by this class are common _ parent parameters, that is, tree structure Algorithms Based on parent-child relationship.
After self-testing, you can only use _ parent, as shown below.
VaR DATA = [
{"_ Id": 1, "_ parent": NULL, "_ Level": 1, "_ is_leaf": false, "item": "main business costs ", & quot; YN & quot;: 64.72 },
{"_ Id": 2, "_ parent": 1, "_ Level": 2, "_ is_leaf": True, "item": "network maintenance costs ", "YN": 64.72}
];
VaR record = ext. Data. Record. Create ([
{Name: '_ id', type: 'int '},
{Name: '_ level', type: 'int '},
{Name: '_ is_leaf', type: 'bool '},
{Name: 'item '},
{Name: 'benbu ', type: 'float '}
]);
VaR store = new Ext. UX. maximgb. TG. adjacencyliststore ({
Autoload: True,
Reader: New Ext. Data. jsonreader ({ID: '_ id'}, record ),
Proxy: New Ext. Data. memoryproxy (data)
});
In this case, the _ LFT and _ rgt parameters are removed, and the store is replaced.
2. Can the tree structure be expanded by default?
Generally, you are used to calling an expansion method at the end of the Code. In the source code, it is found that adjacencyliststore contains an expandall () method, which literally means to expand all nodes. However, in use, it is found that there is no effect. The expandall () method has the following definition: records = This. data. getrange (), records should be the set of all data in this store. After obtaining the data, traverse the data separately and perform the expansion operation. When debugging JS, we found the records. the length is equal to 0. I think it will take a moment to guess that expandall () is better than the load () method of store, and the data is not loaded during the expansion operation. Therefore, you discard the autoload: True configuration in the store. The load and expandall operations are manually written.
Store. Load ();
Store. expandall ();
After this adjustment, you can expand it by default. However, when you change the local data for the test to a remote dynamic call, the result is no longer displayed because of the store. load () is an asynchronous operation, because remote requests are slow. when the load () operation has not returned, the store is called. the expandall () operation is the same as the original error cause.
Later, I will store it myself. the expandall () operation is stored in the store. after the load () operation is completed, it can meet its own needs. load (), or autoload: True, it doesn't matter.
Store. On ("load", function (e ){
Store. expandall ();
});
3. How to customize the prohibition of editing a specified row?
In the code, we can easily make a column uneditable, because the editorgridpanel model is based on the column model. when defining a column, we add an editor attribute, assign an editor object. If we do not assign a value to it, a column cannot be edited, but what about the row? The API does not seem to provide this function, and it seems that it is only implemented by itself. First, let's talk about my own needs:
Use this figure to describe my requirements. My tree structure may be 3-4, and the picture shows 3. The rows that I allow to edit must be the rows of the leaf nodes in the tree, for example, for "Repair" and "maintenance", rather than the data of leaf nodes and root nodes, the data is obtained by counting the corresponding data of the child nodes in the column. For example, "network maintenance cost-Headquarters" is accumulated by "major repair-Headquarters" and "maintenance-Headquarters". The value here cannot be edited. The following conclusions are drawn: the row where the leaf node is located can be edited, and the row where the non-leaf node is located cannot be edited. (Statistics-related code will be discussed later. Here we will only discuss editing issues)
Therefore, we can implement the following code:
Grid. On ("beforeedit", function (e ){
VaR currrecord = E. record;
If (! Currrecord. Get ('_ is_leaf ')){
E. Cancel = true;
}
});
This is the beforeedit event of the Grid. Before editing, determine whether the node is a leaf node. If it is not a leaf node, cancel the editing status. To determine whether the node is a leaf node, you can use the previous _ is_leaf (_ is_leaf must be set, which will affect the "+" symbol pattern in front of the tree structure ), in addition, you can use _ level to determine.
4. How to calculate the value of the subnode of the column where the summary is located?
Here, there are two ways to make statistics. One is to make statistics in the background and pass the data to extjs in JSON format. We will not discuss the scope of this method because we do not need to discuss ^_^ in this way. We need to discuss that the node has no data, only the leaf node contains data, and the node data is the value obtained from the foreground summary.
Here, we will make a statistical summary of the column. First, I thought of the Renderer (rendering) attribute of columnmodel. you can configure this attribute to display editorgridpanel, call the rendering method to modify the text color and content of a cell. Here I will also use this method to summarize data.
I add an Renderer: treenodesum attribute to columnmodel columns to be counted. That is, when this column is displayed, each cell calls the treenodesum method. So we can achieve this:
VaR totalvalue;
Function treenodesum (value, cellmeta, record, rowindex, columnindex, store ){
If (record. Get ('_ is_leaf ')){
Return value;
} Else {
Totalvalue = 0;
Totalnode (record, cellmeta. ID );
Return totalvalue;
}
}
Function totalnode (record, fieldname ){
If (record. Get ('_ is_leaf ')){
Totalvalue + = record. Get (fieldname );
}
VaR mixedcollection = store. Query ("_ parent", record. Get ("_ ID "));
Mixedcollection. Each (function (item, index, length ){
Totalnode (item, fieldname );
});
}
First, call the treenodesum method to determine if (record. get ('_ is_leaf'). If this parameter is set to true, it indicates that the node is a leaf node and a statistical item. Therefore, the node is returned directly because no statistics are required. Instead of leaf nodes, they are all statistical items. Here, I wrote a recursive function to traverse the byte points of subnodes and subnodes. When the subnode is a leaf node, accumulate the values and return them. Then we can summarize the current data and display it to the user, as shown in the previous figure, statistics on the "main business cost" and "network business cost" are collected at the front-end.
Now, a new problem occurs. The Node statistics are displayed on the page. But how can I update the statistics after I modify them? We will discuss it in the next question.
5. How to update statistics in real time?
As mentioned here, the real-time statistics after the modification will of course be immediately associated with the attempt to edit the event. First, find the edited event Afteredit,
Listen to this event. When this event occurs, update the data of the parent node and recursively call it to the root node to end the loop. The Code is as follows:
Grid. On ("Afteredit", function (e ){
VaR currvalue;
VaR parentrecord;
VaR columnname = grid. getcolumnmodel (). getdataindex (E. Column );
VaR currrecord = E. record;
While (currrecord. Get ('_ parent ')! = NULL ){
Parentrecord = store. getat (store. Find ("_ ID", currrecord. Get ('_ parent ')));
Currvalue = parentrecord. Get (columnname );
Currvalue-= E. originalvalue;
Currvalue + = E. value;
Parentrecord. Set (columnname, currvalue );
Parentrecord. Dirty = false;
Parentrecord. Commit ();
Currrecord = parentrecord;
}
});
In this way, the statistical data of the parent node can be updated in real time after the leaf node data is modified. However, when the Code updates the parent node, the parent node is in the edited state with a triangle symbol. When you get the modified data of the store, we don't want to get the data, so we 'd better get rid of the editing status of the statistics node to avoid obtaining the modified data.
6. How do I cancel the edited status and remove the triangle symbol of the prompt?
In fact, the Code has been provided in the Code in the previous section. Here we will explain the following steps:
Parentrecord. Set (columnname, currvalue );
Parentrecord. Dirty = false;
Parentrecord. Commit ();
First, modify the data. At this time, the triangle symbol will appear on the page, prompting that the field has been modified. At this time, we need to set dirty = false, so that the store will not get the modified data, but the interface is not updated at the moment, there is still a triangle symbol prompt, at this time, we need to commit () to remove the triangle symbol.
7. How can I submit modified records in batches at a time?
VaR Results = {};
VaR recordarray = store. getmodifiedrecords ();
VaR recordold;
For (VAR I = 0; I <recordarray. length; I ++ ){
Items = recordarray [I]. getchanges ();
Recordold = recordarray [I]. modified;
For (var key in items ){
If (recordold [Key] = ""){
Results ["item (" + key + "#" + recordarray [I]. Get ("_ id") + "# insert)"] = items [Key];
} Else {
Results ["item (" + key + "#" + recordarray [I]. Get ("_ id") + "# update)"] = items [Key];
}
}
}
In this Code, we first obtain the modified record array, and then traverse this array to obtain each modified field, then judge whether the original value is "" (here I suddenly think that if there is no value ,. will modified be null? If the value is null, the data is added. Otherwise, the data is modified. In this way, the final resules object can be passed as a JSON object through the Params attribute of Ajax.
The JSON String Of The resules object, for example, [{"item (YN #8888 # insert)": 999}, {"item (YN #9999 # update)": 888}].
Because I am using Java struts for programming, the background can be obtained by using the map named item (how to obtain the implementation method of Map-backed actionform without understanding ). The key values of the obtained map are:
YN #8888 # insert (key): 999 (value)
YN #9999 # Update (key): 888 (value)
In this way, we can analyze the key to implement specific services.
8. How to submit modified records in real time?
This function is not used in my code, mainly because it is not good for users to operate the database constantly during the editing process. However, if there is less data, you can try this method. You can register the Afteredit event.
Grid. On ("Afteredit", function (e ){
});
The E parameter passed in this method is actually an event that contains the value information of this data, and the row and column values. With this data, you can get the ownership of this data, then initiate an asynchronous Ajax request. It is best to make a failure judgment here. If there is a prompt that the user fails to save, and it is best to restore the modified value. After the modification is successful, the modification prompt is cleared.