ExtJS:如何在其父容器中使组件最大化?

时间:2014-07-28 10:41:55

标签: javascript extjs extjs5

基本上我想要的是,使用一些可以最大化占用其父组件的组件。 因此我在Ext.window.Window(Panel)中使用Ext.panel.Panel(Window)组件,我可以在多行窗口中以某种方式复制它。必须使用Ext.view.View使用Xtemplate(DataView)呈现窗口 Window具有名为tpl的属性,但我认为,Window 存储属性与其他组件一样,但它具有数据属性。
这是 fiddle 那么如何在Xtemplate窗口中使用Store加载数据?

另一个问题:当我尝试在窗口对象中使用initComponent()启动组件时,它总是在控制台(chrome)中抛出错误:

Uncaught TypeError: Cannot read property 'insert' of undefined   

面板

Ext.create('Ext.panel.Panel', {
    id: 'panel-id',
    itemId: 'panel-id',
    height: 600,
    width: 600,
    resizable: true,
    border: true,
    layout: 'vbox',
    renderTo: Ext.getBody()
});  

模板

var tpl= new Ext.XTemplate(
  '<div>My name is <b>{name}</b></div>'
);

窗口

Ext.create("Ext.window.Window", {
        width: 600,
        maximizable: true,
        constrain: true,
        resizable: false,
        constrainHeader: true,
        constrainTo: 'panel-id',
        renderTo: 'panel-id',
        autoShow: true,
        initComponent: function()
        {
            this.tpl= tpl;
            this.data= {"name":"agpt"};
            this.callParent(arguments);
        }
    });

所以,如果我在窗口内提到initComponent(),我完全没理解为什么窗口没有在面板中进行渲染。感谢

1 个答案:

答案 0 :(得分:2)

考虑到这样的事情:

var store = new Ext.data.Store({
    fields: {name: 'name', type:'string'},
    data: [
        {name: "Foo"},
        {name: "bar"}
    ]
});

您似乎正在尝试实现类似的目标:

var items = [];

store.each(function(record) {
    items.push({
        xtype: 'component'
        ,tpl: "<div>My name is <b>{name}</b></div>"
        ,data: record
    });
});

var panel = new Ext.panel.Panel({
    renderTo: Ext.getBody(),
    title: "Panel with components",
    height: 200,
    width: 600,
    resizable: true,
    border: true,
    layout: 'vbox',
    items: items
});

或那:

var panel2 = new Ext.panel.Panel({
    renderTo: Ext.getBody(),
    title: "Panel with template",
    height: 200,
    width: 600,
    resizable: true,
    border: true,
    layout: 'fit',
    items: [{
        xtype: 'dataview',
        tpl: "<tpl for='.'><div class=\"item\">My name is <b>{name}</b></div></tpl>",
        itemSelector: 'div.item',
        store: store
    }]
});

请参阅小提琴的this fork

一些解释......

首先,windows是浮动组件。它们不打算在面板或任何东西中呈现。它们漂浮在其余部分之上。所以你可能想要更基本的东西。

大多数组件都可以接受tpl配置选项,该选项将与其data相关联,如文档中所述。要使用它,你可以选择最基本的Ext.Component,或者使用更像Ext.panel.Panel这样的东西,例如,如果你想要一个标题,一些可折叠的东西等等。这是我在第一个小组中使用的策略

除了“基本”组件之外,您还有Ext.view.View也使用模板,但这次与商店相关联。在这种情况下,您很可能希望模板中的循环(<tpl for=".">部分)为每条记录渲染一些东西。

最后,关于您的initComponent错误,这是因为this.callParent仅适用于已通过Ext的类管理器传递的方法。在你的代码中,你只是用自定义函数替换类方法,Ext不知道如何将它链接到它的父级,因此范围将是不正确的,所以你会在某个地方得到一个随机错误, 像你所做地。什么会工作......

要么定义自定义类:

Ext.define('My.Window', {
    extend: 'Ext.window.Window'
    // ...
    initComponent: function() {
        this.tpl= view;
        this.data= {"name":"agpt"};
        this.callParent(arguments);
    }
});

var win = new My.Window( ... );

或者使用Ext.override覆盖实例的方法(所有方法都是通过Ext连接方法使callParent工作):

var win = new Ext.Window( ... );
Ext.override(win, {
    initComponent: function() {
        this.tpl= view;
        this.data= {"name":"agpt"};
        this.callParent(arguments);
    }
});

错误......事实上,第二种方法无效,因为initComponent之后已经调用了new Ext.Window( ... )

另一个选择是不依赖callParent并自己做布线:

Ext.create('Ext.window.Window', {
    // ...
    initComponent: function() {
        this.tpl= view;
        this.data= {"name":"agpt"};
        //this.callParent(arguments);
        Ext.window.Window.prototype.initComponent.apply(this, arguments);
    }
});

顺便说一下,我建议不要使用Ext.create,而应使用new关键字。它会在开发模式下立即显示缺失的requires

编辑:最大化父级面板

如果我的评论正确,您希望您的子组件在其父级内可以最大化(而不是在整个浏览器窗口中最大化)。据我所知,没有任何内置的Ext会给你这个;所以你必须自己实施这样的行为。

第一个想法可能是使用setLayout方法在vboxfit之间交换布局。不幸的是,正如文档中强调的那样:

  

注意:在将组件渲染到DOM之后,此方法不能用于更改布局的“类型”。

没有运气。所以你必须做一些复杂的事情。我看到它的方式,你应该给你的父面板一个card布局,并在其中放入两个容器:一个具有框布局,另一个具有合适的布局。要“最大化”子组件,然后将其从框布局容器移动到适合容器,并将卡切换到后者。要从最大化恢复,请将子组件放回原始位置,然后将卡切换回盒子容器。

以下是一些示例代码(以及另一个fork of the fiddle):

var store = new Ext.data.Store({
    fields: {name: 'name', type:'string'},
    data: [
        {name: "Foo"},
        {name: "bar"}
    ]
});

var items = [];

store.each(function(record) {
    items.push({
        xtype: 'panel'
        ,tpl: "<div>My name is <b>{name}</b></div>"
        ,data: record
        ,tools: [{
            type: 'maximize'
            ,handler: function(t) {
                this.disable();
                this.up().down('tool[type=restore]').enable();

                var rootPanel = this.up('#rootPanel'),
                    fitCt = rootPanel.down('#fitCt'),
                    panel = this.up('panel');
                panel.lastIndex = panel.ownerCt.items.indexOf(panel);
                fitCt.add(panel);
                rootPanel.getLayout().setActiveItem(fitCt);
            }
        },{
            type: 'restore'
            ,disabled: true
            ,handler: function() {
                this.disable();
                this.up().down('tool[type=maximize]').enable();

                var rootPanel = this.up('#rootPanel'),
                    listCt = rootPanel.down('#listCt'),
                    panel = this.up('panel');
                listCt.insert(panel.lastIndex, panel);
                rootPanel.getLayout().setActiveItem(listCt);
            }
        }]
    });
});

var panel = new Ext.panel.Panel({
    renderTo: Ext.getBody(),
    title: "Panel with components",
    itemId: 'rootPanel',
    height: 200,
    width: 600,
    resizable: true,
    border: true,
    layout: 'card',
    items: [{
        xtype: 'container',
        itemId: 'listCt',
        layout: {
            type: 'vbox',
            align: 'stretch'
        },
        defaults: {
            margin: 5
        },        
        items: items
    },{
        xtype: 'container',
        itemId: 'fitCt',
        layout: 'fit',
        items: []
    }]
});