ExtJS: How to create own Class with other ExtJS components?
-
21-12-2019 - |
質問
I am trying to create Panel
class object with different items. Basically its related with Desktop app in ExtJS.
DetailView.js
Ext.define("App.view.DetailView", {
extend : 'Ext.panel.Panel',
alias : 'widget.asset-panel',
itemId : 'Detail-view',
region : 'center',
initComponent : function() {
this.items = [ comboboxes, customPanel ];
this.callParent(arguments);
}
});
I am trying to create items
component in both the way i.e. using xtype
and using Ext.create()
way. I am not sure which is correct and how should I got about it.. below is comboboxes
variable inside DetailView.js
var comboboxes = {
xtype : 'form',
border : false,
padding : '5 5 5 5',
items : [ {
layout : 'column',
border : false,
width : 600,
items : [ {
xtype : 'combobox',
columnWidth : .15,
itemId : 'filter-1',
store : [ 'Employee', 'Manager', 'TeamLead' ]
}, {
xtype : 'combobox',
columnWidth : .15,
margin : '0, 0, 0, 15',
store : [ 'Keywords', 'Names' ]
}, {
xtype : 'combobox',
columnWidth : .15,
margin : '0, 0, 0, 15',
store : [ 'Some Data here' ]
}]
} ]
};
So far so good, If I am keeping this.items = [comboboxes]
in DetailView
class its working fine without any issue. but when I am trying to add other component, such as customPanel inside DetailView.js
var custom = Ext.create('Ext.panel.Panel', {
itemId : 'panel_1',
height : 300,
border : false,
layout : 'card',
items : [ {
xtype : 'container',
itemId : 'listCt',
layout : {
type : 'vbox',
align : 'stretch'
},
defaults : {
margin : 2
},
items : []
}, {
xtype : 'container',
itemId : 'fitCt',
layout : 'fit'
} ]
});
I tried both the way to initialize panel, as in above and by using initComponent()
but every time it gives error:
Uncaught TypeError: Cannot set property 'component' of null ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.finishRenderItems ext-all.js:22
Ext.cmd.derive.finishRender ext-all.js:22
Ext.cmd.derive.privates.finishRenderChildren ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.afterRender ext-all.js:22
Ext.cmd.derive.privates.finishRender ext-all.js:22
Ext.cmd.derive.render ext-all.js:22
Ext.cmd.derive.privates.doAutoRender ext-all.js:22
Ext.cmd.derive.show ext-all.js:22
Ext.define.restoreWindow Desktop.js?_dc=1406637300888:388
Ext.define.onShortcutItemClick Desktop.js?_dc=1406637300888:199
fire ext-all.js:22
doFireEvent ext-all.js:22
a.doFireEvent ext-all.js:22
fireEventArgs ext-all.js:22
fireEvent ext-all.js:22
Ext.cmd.derive.processUIEvent ext-all.js:22
Ext.cmd.derive.handleEvent ext-all.js:22
Ext.cmd.derive.doFire ext-all.js:22
Ext.cmd.derive.fire ext-all.js:22
Ext.cmd.derive.doDispatchEvent ext-all.js:22
Ext.cmd.derive.dispatch ext-all.js:22
Ext.cmd.derive.dispatch ext-all.js:22
Ext.cmd.derive.doPublish ext-all.js:22
Ext.cmd.derive.publish ext-all.js:22
Ext.cmd.derive.onDelegatedEvent ext-all.js:22
(anonymous function)
it gives error when reinitialing window. i.e. it work only in first execution, but not in second. I doubt if components are being render and destroyed properly. What could be the possible reason ? any possible solution ?
解決
It seems that you're reusing the components after they've been destroyed:
initComponent : function() {
// comboboxes & customPanel will be the same instances
// for every App.view.DetailView you create
this.items = [ comboboxes, customPanel ];
this.callParent(arguments);
}
The same here:
items : [{
xtype : 'container',
itemId : 'listCt',
// ...
// The component in this items variable will be destroyed when their
// parent is destroyed, and won't be usable again after that
items : items
// ...
}]
You've got two solid ways to define custom classes with preset items.
First, you can use inline (xtype) configuration. This has the advantage of lazy initialization; further, Ext will create separate instances of the items each time you create an instance of your custom component.
For example:
Ext.define('My.Panel', {
extend: 'Ext.panel.Panel'
,items: [{
xtype: 'textfield'
,fieldLabel: "My field"
},{
xtype: 'component'
,html: "Bla bla bla"
}]
});
var myFirstPanel = new My.Panel({
renderTo: Ext.getBody()
,title: "First Panel"
});
var mySecondPanel = new My.Panel({
renderTo: Ext.getBody()
,title: "Second Panel"
});
If you need more involved treatment, hook on the initComponent
method, but be sure to create new instances of the child items in there.
Ext.define('My.InitComponentPanel', {
extend: 'Ext.panel.Panel'
,customFieldLabel: "Example field"
,initComponent: function() {
// initComponent will be called each time a InitComponentPanel
// is created, and a new textfield will be created for each
this.items = [
new Ext.form.field.Text({
fieldLabel: this.customFieldLabel
});
];
this.callParent(arguments);
}
});
var panel1 = new My.InitComponentPanel({
renderTo: Ext.getBody()
,customFieldLabel: "First field"
});
// will destroy panel1's items, but no problem
panel1.destroy();
var panel2 = new My.InitComponentPanel({
renderTo: Ext.getBody()
,customFieldLabel: "Second field"
});
The same goes if you use Ext components directly (without extending them); don't use existing components in multiple places.
// Inline (uninstantiated) items are always fine
var panel = new Ext.panel.Panel({
renderTo: Ext.getBody()
,items: [{
xtype: 'checkbox'
,boxLabel: "My checkbox"
}]
});
// You can also create children beforehand
var checkbox = new Ext.form.field.Checkbox;
var panel2 = new Ext.panel.Panel({
renderTo: Ext.getBody()
,items: [checkbox]
});
// But don't reuse the checkbox for another panel
var panel3 = new Ext.panel.Panel({
renderTo: Ext.getBody()
// this will remove the unique checkbox instance from panel2
// and if panel2 has been destroyed meanwhile, it will crash
,items: [checkbox]
});
Don't forget that you can also add/remove items from a container that has already been created with its add
, insert
, remove
, etc. methods (but don't touch the items
property directly!).