The reason is that the customer has many kinds of materials and there are as many as one thousand. If a single Combobox is used, it is difficult to quickly find a material in actual use, I use two comboboxes that contain material classification and material brands to form cascading filtering. The problem lies exactly here. If multiple controls are used in a field of roweditor, the initialization and Change events of each control should be processed. No good solution has been found on the Internet. After three days of debugging, I finally solved the problem and pasted my code:
Copy codeThe Code is as follows: var editor = new Ext. ux. grid. RowEditor ({
SaveText: 'OK ',
CancelText: "abandon ",
CommitChangesText: 'Please confirm or stop modifying ',
ErrorText: 'error'
});
// When canceled, empty records are deleted based on whether the value of the keyword segment is null.
Editor. on ("canceledit", function (editor, pressed)
{
If (pressed & editor. record. get ("materialid") = 0)
{
Store. remove (editor. record );
}
}, This );
/*
Afterstart is a self-added event, because if you want to initialize your control in the beforeedit event, it is impossible, because when beforeedit, The roweditor control has not been rendered, so, I added the afterstart event, which is called immediately after the display of roweditor, so you can initialize it here.
You must note that you can use the roweditor control to traverse the custom composite Control.
Editor. items. items [0], here it is not my re-writing, but the items of the roweditor control is not a set, but an object. Here I also spent some time, finally, the editor object is output through firebug.
Editor. items. items [0] is the compositefield component. Through the items set of this component, you can access its child components in a standard form. Then you can initialize the component.
Because the data of the last combobox is to be loaded after being selected through the first two comboboxes cascade, the data is loaded here for initialization, but note that I am executing it in callback, because the load action of jsonstore is asynchronous, you must use the callback of the callback event to initialize the value after the data is loaded successfully.
*/
Editor. on ("afterstart", function (editor, rowIndex)
{
Var record = store. getAt (rowIndex );
Editor. items. items [0]. items. items [0]. setValue (record. get ("setid "));
Editor. items. items [0]. items. items [1]. setValue (record. get ("category "));
Var t_store = editor. items. items [0]. items. items [2]. getStore ();
T_store.load ({
Params: {category: record. get ("category"), setid: record. get ("setid ")},
Callback: function (r, options, success ){
If (success)
Editor. items. items [0]. items. items [2]. setValue (record. get ("materialid "));
}
});
}, This );
/*
The validateedit event is executed when the validation is performed to verify the values of each control in roweditor. Here, I executed a custom verification action, because I don't want users to add repeated materials, I traverse jsonstore and compare the material values of each record with the selected material values, prompt the user not to join again
*/
Editor. on ("validateedit", function (editor, obj, record, rowIndex ){
Var materialid = editor. items. items [0]. items. items [2]. getValue ();
Var exist = false;
Ext. each (store. getRange (), function (o, I ){
If (o! = Record & o. get ("materialid") = materialid)
{
Exist = true;
Return (false );
}
});
If (exist)
{
Ext. MessageBox. alert ("system prompt", "do not add again ");
Store. remove (record );
}
Return (! Exist );
}, This );
/*
AfterEdit is executed after verification. The most important action here is to assign values to some attributes of the record being edited because compsitefield is used, roweditor cannot assign the selected value to the correct attribute of the record. We need to manually assign the user's selection to the corresponding field. materialid is the user's selected item number, the model corresponds to the model of the item.
Why do we need to assign a model? Because model is a column value, if it is not assigned, it is null.
*/
Editor. on ("afteredit", function (editor, obj, record, rowIndex ){
Record. set ("materialid", editor. items. items [0]. items. items [2]. getValue ());
Record. set ("model", editor. items. items [0]. items. items [2]. getRawValue ());
}, This );
The above is the definition of roweditor and the processing of the event. Next, insert roweditor as a plug-in to gridpanelCopy codeThe Code is as follows :{
Xtype: "grid ",
Title: "Product BOM ",
Layout: "fit ",
Store: store,
EnableDragDrop: false,
Border: false,
Frame: false,
AutoScroll: true, plugins: [editor],
Sm: sm,
Height: 340,
ClicksToEdit: 2,
AutoWidth: true,
ViewConfig: {forceFit: true, autoFill: true, markDirty: false}
}
Next, let's take a look at the column definition of gridpanel. Here, you can see how composite is used.Copy codeThe Code is as follows: columns :[{
Header: "item name/model ",
DataIndex: "model ",
Width: 200,
MenuDisabled: true,
Editor:
{
// Define the editor
Xtype: "compositefield ",
Name: "compositefield ",
Items :[
{
Xtype: "combo ",
Mode: "local ",
Name: "sets ",
Width: 80,
FieldLabel: "applicable product brands ",
EmptyText: "select ",
ValueField: "id ",
LazyInit: false,
Value: this. data? This. data. title :"",
HiddenName: "setid ",
HiddenValue: this. data? This. data. setid :"",
DisplayField: "title ",
TypeAhead: false,
ForceSelection: true,
Editable: true,
Listeners :{
"Change": function (combo, newvalue, oldvalue)
{
// Process the change event of the brand. After the brand is selected, reload the combobox. The editor is an example of roweditor defined previously.
Var category = editor. items. items [0]. items. items [1];
Var material = editor. items. items [0]. items. items [2];
Var c = category. getValue ();
Var store = material. getStore ();
Store. load ({
Params: {setid: newvalue, category: c },
Callback: function (r, options, success ){
If (success)
Material. setValue ("");
}
});
}
},
TriggerAction: "all ",
Store: new Ext. data. JsonStore ({
Url: "<% = script_path %> data. asp ",
Root: "data", autoDestroy: true,
RemoteSort: true,
Listeners: {"load": function (store, records, option ){
Var s = Ext. data. record. create ([{name: "id", type: "int" },{ name: "title", type: "string"}]);
Store. add (new s ({id: 0, title: ""}))
}},
BaseParams: {op: "setList "},
TotalProperty: "total ",
AutoLoad: true,
Fields: ["title", "id"]
})
},
{
Xtype: "combo ",
Mode: "local", width: 60,
Name: "category ",
FieldLabel: "category ",
EmptyText: "select ",
ValueField: "category ",
LazyInit: false,
Value: this. data? This. data. category :"",
DisplayField: "category ",
TypeAhead: false, forceSelection: true,
TriggerAction: "all ",
Listeners :{
"Change": function (combo, newvalue, oldvalue)
{
// Process the change event of the category. After selecting the brand, reload the combobox. The editor is the roweditor instance defined previously.
Var sets = editor. items. items [0]. items. items [0];
Var material = editor. items. items [0]. items. items [2];
Var setid = sets. getValue ();
Var store = material. getStore ();
Store. load ({
Params: {category: newvalue, setid: setid },
Callback: function (r, options, success ){
If (success)
Material. setValue ("");
}
});
}
},
Store: new Ext. data. JsonStore ({
Url: "<% = script_path %> data. asp ",
Root: "data", autoDestroy: true,
RemoteSort: true,
BaseParams: {op: "materialCategoryList "},
TotalProperty: "total ",
AutoLoad: true,
Fields: ["category"]
})
},
{
Xtype: "combo ",
ForceSelection: true,
Editable: true,
Mode: "local ",
Name: "material ",
FieldLabel: "material ",
EmptyText: "select materials ",
ValueField: "id ",
AllowBlank: false,
DisplayField: "model ",
Width: 250,
LazyInit: false,
TypeAhead: false,
TriggerAction: "all ",
Listeners :{
"Change": function (combo, newvalue, oldvalue)
{
// Be sure to pay attention here !!! If you do not have the following two sentences, you will find that the displayed values do not change and you cannot update them even if you click OK. Why? Roweditor checks whether validateedito and afteredit are called by checking the isdirty attribute of record. It checks whether the control values of each column change. Because of the item model column, the corresponding value is compositefield. Therefore, we must change the value of compositefield before roweditor can call validedit and afteredit. In addition, the value of compositefield is also called and displayed in the column.
Var comp = editor. items. items [0];
Comp. setRawValue (combo. getRawValue ());
}
},
Store: new Ext. data. JsonStore ({
Url: "<% = script_path %> data. asp ",
Root: "data", autoDestroy: true,
RemoteSort: true,
BaseParams: {op: "materialList "},
TotalProperty: "total ",
AutoLoad: false,
Fields: ["model", "id"]
})}
]
}
},
{
Header: "quantity ",
DataIndex: "qty ",
Width: 50,
MenuDisabled: true,
Editor :{
Xtype: 'numberfield ',
MinValue: 1,
AllowDecimals: false
}
}
,{
Header: "color ",
DataIndex: "color ",
Width: 60,
MenuDisabled: true
}
,{
Header: "size ",
DataIndex: "size ",
Width: 60,
MenuDisabled: true
}
]
}
]
Share this with friends in need