ExtJS: как создать собственный класс с другими компонентами ExtJS?

Я пытаюсь создать объект класса Panel с разными элементами. В основном это связано с настольным приложением в 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);
   }
});  

Я пытаюсь создать компонент items как с помощью xtype, так и с помощью Ext.create(). Я не уверен, что правильно и как мне об этом узнать. Ниже приведена переменная comboboxes внутри 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' ]
    }]
} ]
};  

Пока все хорошо, если я сохраняю this.items = [comboboxes] в классе DetailView, он работает нормально без каких-либо проблем. но когда я пытаюсь добавить другой компонент, например customPanel внутри 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'
} ]
});  

Я пробовал как инициализировать панель, как показано выше, так и с помощью initComponent(), но каждый раз выдает ошибку:

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)  

выдает ошибку при переинициализации окна. т.е. работает только в первом исполнении, но не во втором. Я сомневаюсь, что компоненты правильно визуализируются и уничтожаются. Что может быть возможной причиной? любое возможное решение?


person agpt    schedule 29.07.2014    source источник


Ответы (1)


Похоже, вы повторно используете компоненты после их уничтожения:

initComponent : function() {
    // comboboxes & customPanel will be the same instances 
    // for every App.view.DetailView you create
    this.items = [ comboboxes, customPanel ];
    this.callParent(arguments);
}

Тут то же самое:

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

    // ...
}]

У вас есть два надежных способа определить пользовательские классы с предустановленными элементами.

Во-первых, вы можете использовать встроенную (xtype) конфигурацию. Это имеет преимущество ленивой инициализации; кроме того, Ext будет создавать отдельные экземпляры элементов каждый раз, когда вы создаете экземпляр своего пользовательского компонента.

Например:

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"
});

Если вам нужно более сложное лечение, подключитесь к методу initComponent, но обязательно создайте там новые экземпляры дочерних элементов.

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"
});

То же самое происходит, если вы используете компоненты Ext напрямую (без их расширения); не используйте существующие компоненты в нескольких местах.

// 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]
});

Не забывайте, что вы также можете добавлять/удалять элементы из контейнера, который уже был создан с помощью его методов add, insert, remove и т. д. (но не касайтесь свойства items напрямую!).

person rixo    schedule 29.07.2014
comment
о чувак.!! поэтому, если мы определяем наш класс, скажем Ext.define("My.CustomPanel",{...}), поэтому для повторного использования этого компонента после каждого уничтожения я должен повторно инициализировать его, используя ключевое слово new !! ? (поскольку это настольное приложение, поэтому мне приходится использовать их чаще, когда я закрываю экземпляр Ext.window.Window в приложении) - person agpt; 29.07.2014
comment
Да, вы должны создать один экземпляр компонента для каждого места, где он вам нужен, и вы должны создавать новые после их уничтожения. С помощью ключевого слова new или Ext.create, которые примерно эквивалентны, или используйте xtype вашего компонента (или xclass в Ext5/Touch) в конфигурации какого-либо контейнера. Однако можно переместить существующий экземпляр компонента, добавив его в другой контейнер; если вы сделаете это до уничтожения первого контейнера, это сработает. - person rixo; 29.07.2014
comment
Вы также можете посмотреть на autoDestroy вариант, но я бы не стал самостоятельно управлять жизненным циклом компонентов (с тех пор вам придется самостоятельно уничтожать дочерние компоненты, чтобы предотвратить утечку памяти)... - person rixo; 29.07.2014
comment
это меня когда-нибудь убьет.. Что и как все это понимать? Я пытаюсь прочитать это в extjs apidoc, но на данный момент это не очень хорошо для меня пахнет. кстати большое спасибо, что объяснили мне это - person agpt; 29.07.2014
comment
Не могли бы вы указать мне какой-нибудь ресурс, любую ссылку/ресурс/электронную книгу, чтобы точно понять, как работает эта инициализация и уничтожение. На самом деле я выполняю очень сложную задачу, например, создание панелей вложенных компонентов внутри панелей, контейнеров, загрузка их хранилищ, их инициализация и т. д. - person agpt; 29.07.2014
comment
Извините, я действительно не знаю, где вы можете найти документы об этом, вы получите их с опытом... Я написал о initComponent в другом вопросе, это может помочь. Но жизненный цикл с Ext не так сложен, если вы не будете слишком сильно оборачивать фреймворк, он будет по сути автоматическим (спасибо autoDestroy). - person rixo; 29.07.2014