在ExtJS组件中,如何将config:{}项转发到子组件

时间:2013-01-17 17:43:33

标签: extjs model-view-controller extjs4 extjs4.1 extjs4.2

我正在尝试编写一个可重复使用的项目选择面板,其中用户有一个网格,其中包含可供选择的项目以及一个可用于过滤网格内容的小文本字段。现在(简化)视图代码如下所示,工作

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    extend: 'Ext.panel.Panel',
    require: 'MyApp.view.items.SimpleItemGrid',
    alias: 'widget.ItemSelectorPanel',
    layout: 'form',

    config: {
        itemStore: false
    },

    constructor: function(config) {
        this.initConfig(config);

        this.superclass.constructor.call(this, config);

        this.add([
            {
                fieldLabel: 'Filter',
                name: 'filter'
            },
            {
                xtype: 'SimpleItemGrid',
                collapsible: true,
                store: this.getItemStore()
            }
        ]);

        return this;
    }
});

正如您所看到的,ItemSelectorPanel使用config属性来公开一个接口,其中调用站点可以指定要使用的项目存储。

呼叫站点(在这种情况下,面板被添加到TabPanel中):

var panelToAdd = {
    xtype: 'panel',
    title: 'New Selection',
    closable: true,
    padding: 10,
    items: [{
        title: 'Select node',
        xtype: 'ItemSelectorPanel',
        itemStore: itemStore
    }]
};

现在,我喜欢ExtJS 4的声明式风格以及它如何帮助遵循MVC模式。我希望在视图中可以使用最少量的代码。不幸的是,不起作用

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    /* ... same as above ... */

    constructor: function(config) {
        this.initConfig(config);

        this.superclass.constructor.call(this, config);

        return this;
    },

    items: [
            {
                fieldLabel: 'Filter',
                name: 'filter'
            },
            {
                xtype: 'SimpleItemGrid',
                collapsible: true,
                store: this.getItemStore   // <-- interesting part
            }
    ]
});

有没有办法通过父属性config属性以声明方式公开嵌套/子组件的配置

4 个答案:

答案 0 :(得分:5)

一般的第一件事

从不在类定义中的函数外添加对象,除非您确切知道要执行的操作。因为如果这样做,所有实例将共享该对象的相同实例。我想我不需要提到它会导致什么......

如果你需要在那里放置一个对象,你应该在构造函数中克隆它。

到你的代码

我不知道this.initConfig(config);做了什么,但config变量不是你的类中的变量,它是构造函数参数中的变量。我建议您使用initComponent()进行初始化而不是constructor(),除非您已经定义了使用构造函数的需求,在您的情况下您似乎没有。

此外,'config'不会被转发,因为它不会被执行 - > gt; bottom但是bottom-&gt; up,其中一个配置得到提升,所有其他属性都已经(已经)继承。

我仍然不确切知道你的目标是什么,因此我不能给你任何建议你应该怎么做但我可以肯定地说你这样做会导致问题。

修改

我仍然不确定我是否完全了解您的需求,但以下情况应该有效(如果您也需要听众,您可以查看 Ext.util.Bindable mixin)

Ext.define('MyApp.view.items.ItemSelectorPanel', {
    extend: 'Ext.panel.Panel',
    require: 'MyApp.view.items.SimpleItemGrid',
    alias: 'widget.ItemSelectorPanel',
    layout: 'form',

    initComponent: function() {
        // Initialize the store (might be a instance or a storeId)
        var store;
        if (this.itemStore) {
            store = Ext.data.StoreManager.lookup(store);
        }
        this.itemStore = store || null;
        // Add is not valid (at least not before the parent inits are executed)
        this.items = [{
            fieldLabel: 'Filter',
            name: 'filter'
        }, {
            xtype: 'SimpleItemGrid',
            collapsible: true,
            store: this.getItemStore()
        }];

        this.callParent(arguments);
    },

    getItemStore: function() {
        return this.itemStore;
    }
});

答案 1 :(得分:2)

不,你不能按照你所描述的方式去做。原因很简单,我们以此为例:

Ext.define('MyClass', {
    someProp: this.foo(),

    foo: function(){
        return bar;
    }
});

这里,我们调用define()方法,并将它作为配置传递给它。因此,整个对象(包括对foo()的调用)在它甚至传递给define之前进行了求值,因此类/方法在那时甚至不存在。

即使你可以这样做,这也是foo是类的实例方法的复杂性,但是你尝试调用它的方式就好像它是一个静态方法。

所以,答案是,你需要使用某种方法来实现这一点,initComponent通常比构造函数更受欢迎。

答案 2 :(得分:1)

您可以在类的声明中定义项目,但在声明时不能从您的班级调用任何方法。要解决此问题,请仅定义没有存储的项目,而不是使用initComponent方法为视图设置存储。

答案 3 :(得分:1)

我没有看到解决原始问题的答案。这是我发现的工作......

创建myClass的实例,传入值为'bar'的配置'foo'

var myClassInstance = Ext.create('MyApp.view.myClass', {
    foo: 'bar'
});

myClass定义如下:

Ext.define('MyApp.view.myClass', {
extend: 'Ext.container.Container',
alias: 'widget.myclass',

config: {
    foo: 'defaultVal'
},

constructor: function(configs) {
    this.callParent(arguments);  //create class, calls initComponent

    var try1 = getFoo(); //try1 is 'defaultVal'
    this.initConfig(configs);  //initializes configs passed in constructor
    var try2 = getFoo(); //try2 is 'bar' 
},

initComponent: function() {
    //myClass declaration here ...

    this.callParent();
}