【问题标题】:Pass up child component's config to parent将子组件的配置传递给父组件
【发布时间】:2013-01-01 17:16:08
【问题描述】:

通常,要定义网格类型,我会这样做:

Ext.define('MyApp.view.MyGrid', {
  extend: 'Ext.grid.Panel',
  alias: 'widget.myGrid',
  store: 'MyStore',
  columns: [...],
}

然后我通过它的 xtype 'myGrid' 将它添加到容器或布局中。

我想做的是定义一个可重用的自定义组件,它要么扩展Ext.grid.Panel,要么接受相同的配置(例如列),但实际上是一个包含网格和其他内容的容器。

Ext.define('MyApp.components.ContainedGrid', {
  extend: 'Ext.container.Container' //or Ext.grid.Panel, whatever works
  alias: 'widget.containedGrid',
  layout: 'card',
  items: [
    {someObject}, //doesn't matter what this is
    {aGrid}, //the grid that should receive the configs from the caller
  ],
}

理想情况下,该组件可以像常规Ext.grid.Panel 对象一样配置,并且这些配置应该真正应用于 items 数组中第二个定义的网格。

换句话说,类似下面的内容应该呈现一个包含卡片布局的窗口,其中第二张卡片应该是网格,并为容器提供列和存储。

Ext.create('Ext.window.Window',  {
  title: 'hi',
  layout: 'fit',
  items: {
    xtype: 'containedGrid',
    store: myStore,
    columns: [...],
  },
});

从逻辑上讲,我只想说提供给容器的配置适用于其组件之一,但我不知道如何执行。有什么想法吗?

编辑: 简而言之,我要做的是创建一个组件,该组件的配置就像网格一样,但实际上是一个包含网格以及其他一些东西的容器。这个组件会被多次使用,所以我想把它打包成一个可复用的组件。

【问题讨论】:

    标签: extjs extjs4


    【解决方案1】:

    为 gridconfig 定义一个属性

    Ext.define('MyApp.components.ContainedGrid', {
      extend: 'Ext.container.Container' //or Ext.grid.Panel, whatever works
      alias: 'widget.containedGrid',
      layout: 'card',
      /**
       * @cfg {object} gridCfg
       */
    
      initComponent: function(){
         var gridCfg = { xtype: 'grid' };
         if(this.gridCfg)
              gridCfg = Ext.apply(gridCfg ,this.gridCfg);
         if (this.items) // we assume if set it will be always array!
              this.items.push(gridCfg);
         else
              this.items = [gridCfg];
         delete this.gridCfg; // we no longer need this property here
         this.callParent(arguments);
      }
    }
    

    还有用例:

    Ext.create('Ext.window.Window',  {
      title: 'hi',
      layout: 'fit',
      items: {
        xtype: 'containedGrid',
        gridCfg: {
           store: myStore,
           columns: [...]
        }
      },
    });
    

    更新

    我想我现在明白你在寻找什么了。要将侦听器直接注册到容器上,您需要中继事件。我举了一个例子,至少可以传递视图的事件(应该是最多的)。您还可以转发表格和特征的事件(渲染后首先显示特征)。这是一个 JSFiddle,它将容器中的所有事件打印到控制台中。

    Ext.define('Ext.ux.ContainedGrid', {
          extend: 'Ext.container.Container',
          alias: 'widget.containedGrid',
          layout: 'card',
          /**
           * @cfg {object} gridCfg
           */
    
          /**
           * @private {object} grid
           */
          initComponent: function(){
             var me = this,
                 grid;
             // provide some default settings for the grid here, 
             // which can be overriden by each instance
             var gridCfg = { }; // the defaulttype is defined on the componentmanager call
             me.gridCfg = me.gridCfg ? Ext.apply(gridCfg ,me.gridCfg) : gridCfg;
    
             me.grid = me.getGrid();
    
             if (me.items && Ext.isArray(me.items)) 
                  me.items.push(me.grid);
             else if(me.items)
                  me.items = [me.items, me.grid];
             else
                  me.items = [me.grid];
             delete me.gridCfg; // we no longer need this property here
             // Relay events from the View whether it be a LockingView, or a regular GridView
             this.relayEvents(me.grid, [
                    /**
                     * @event beforeitemmousedown
                     * @inheritdoc Ext.view.View#beforeitemmousedown
                     */
                    'beforeitemmousedown',
                    /**
                     * @event beforeitemmouseup
                     * @inheritdoc Ext.view.View#beforeitemmouseup
                     */
                    'beforeitemmouseup',
                    /**
                     * @event beforeitemmouseenter
                     * @inheritdoc Ext.view.View#beforeitemmouseenter
                     */
                    'beforeitemmouseenter',
                    /**
                     * @event beforeitemmouseleave
                     * @inheritdoc Ext.view.View#beforeitemmouseleave
                     */
                    'beforeitemmouseleave',
                    /**
                     * @event beforeitemclick
                     * @inheritdoc Ext.view.View#beforeitemclick
                     */
                    'beforeitemclick',
                    /**
                     * @event beforeitemdblclick
                     * @inheritdoc Ext.view.View#beforeitemdblclick
                     */
                    'beforeitemdblclick',
                    /**
                     * @event beforeitemcontextmenu
                     * @inheritdoc Ext.view.View#beforeitemcontextmenu
                     */
                    'beforeitemcontextmenu',
                    /**
                     * @event itemmousedown
                     * @inheritdoc Ext.view.View#itemmousedown
                     */
                    'itemmousedown',
                    /**
                     * @event itemmouseup
                     * @inheritdoc Ext.view.View#itemmouseup
                     */
                    'itemmouseup',
                    /**
                     * @event itemmouseenter
                     * @inheritdoc Ext.view.View#itemmouseenter
                     */
                    'itemmouseenter',
                    /**
                     * @event itemmouseleave
                     * @inheritdoc Ext.view.View#itemmouseleave
                     */
                    'itemmouseleave',
                    /**
                     * @event itemclick
                     * @inheritdoc Ext.view.View#itemclick
                     */
                    'itemclick',
                    /**
                     * @event itemdblclick
                     * @inheritdoc Ext.view.View#itemdblclick
                     */
                    'itemdblclick',
                    /**
                     * @event itemcontextmenu
                     * @inheritdoc Ext.view.View#itemcontextmenu
                     */
                    'itemcontextmenu',
                    /**
                     * @event beforecontainermousedown
                     * @inheritdoc Ext.view.View#beforecontainermousedown
                     */
                    'beforecontainermousedown',
                    /**
                     * @event beforecontainermouseup
                     * @inheritdoc Ext.view.View#beforecontainermouseup
                     */
                    'beforecontainermouseup',
                    /**
                     * @event beforecontainermouseover
                     * @inheritdoc Ext.view.View#beforecontainermouseover
                     */
                    'beforecontainermouseover',
                    /**
                     * @event beforecontainermouseout
                     * @inheritdoc Ext.view.View#beforecontainermouseout
                     */
                    'beforecontainermouseout',
                    /**
                     * @event beforecontainerclick
                     * @inheritdoc Ext.view.View#beforecontainerclick
                     */
                    'beforecontainerclick',
                    /**
                     * @event beforecontainerdblclick
                     * @inheritdoc Ext.view.View#beforecontainerdblclick
                     */
                    'beforecontainerdblclick',
                    /**
                     * @event beforecontainercontextmenu
                     * @inheritdoc Ext.view.View#beforecontainercontextmenu
                     */
                    'beforecontainercontextmenu',
                    /**
                     * @event containermouseup
                     * @inheritdoc Ext.view.View#containermouseup
                     */
                    'containermouseup',
                    /**
                     * @event containermouseover
                     * @inheritdoc Ext.view.View#containermouseover
                     */
                    'containermouseover',
                    /**
                     * @event containermouseout
                     * @inheritdoc Ext.view.View#containermouseout
                     */
                    'containermouseout',
                    /**
                     * @event containerclick
                     * @inheritdoc Ext.view.View#containerclick
                     */
                    'containerclick',
                    /**
                     * @event containerdblclick
                     * @inheritdoc Ext.view.View#containerdblclick
                     */
                    'containerdblclick',
                    /**
                     * @event containercontextmenu
                     * @inheritdoc Ext.view.View#containercontextmenu
                     */
                    'containercontextmenu',
                    /**
                     * @event selectionchange
                     * @inheritdoc Ext.selection.Model#selectionchange
                     */
                    'selectionchange',
                    /**
                     * @event beforeselect
                     * @inheritdoc Ext.selection.RowModel#beforeselect
                     */
                    'beforeselect',
                    /**
                     * @event select
                     * @inheritdoc Ext.selection.RowModel#select
                     */
                    'select',
                    /**
                     * @event beforedeselect
                     * @inheritdoc Ext.selection.RowModel#beforedeselect
                     */
                    'beforedeselect',
                    /**
                     * @event deselect
                     * @inheritdoc Ext.selection.RowModel#deselect
                     */
                    'deselect'
                ]);
             me.callParent(arguments);
          },
          getGrid: function() {
             if(this.grid)
                 return this.grid;
             return this.grid = Ext.ComponentManager.create(this.gridCfg,'grid');;
          }
    
    });
    

    【讨论】:

    • 这似乎工作得很好。一个值得注意的警告:1)我需要在gridCfg中设置一个itemId,以便控制器监听#itemId的事件,因为xtype'containedGrid'不会是唯一的,并且外部组件的xtype不会引用网格。
    • @romacafe 好吧,没有什么能阻止你这样做。也许我没听懂你,你觉得这有什么缺点吗?基本上你只需要提供一个唯一的路径,如果你有两个在同一个容器中,那么只需要将 itemId 放在网格上,否则我会尝试识别容器。如果您想使用该组件功能,它只需要是一个 itemId,否则您可以使用任何,甚至是自定义属性来查询。
    • 我不想听起来不欣赏,这非常有帮助!最理想的解决方案是允许开发人员以与标准网格相同的方式完全使用它,只更改 xtype,但我觉得它不切实际。 (我猜你必须扩展网格,然后用它自己的布局和/或项目集合弄脏,但到目前为止我所有的尝试都没有成功)。要求嵌套配置和 itemId 是相对较小的让步,也是我目前最好的选择。
    • @romacafe 你误会我的意思了,你听起来并没有不欣赏。我只是不明白您在哪里看到(看到?)这种方法的问题。那可能是因为我不知道您要达到的目标。您可以将 is 用作网格,您只需要先访问网格,就像您需要首先从网格获取视图以进行某些操作一样。不知道这是否对您有帮助,但我会扩展我的答案,希望能更接近您正在寻找的内容。
    • @romacafe 查看我的编辑。我认为这将更接近您正在寻找的内容。
    【解决方案2】:

    重写initComponent方法:

    Ext.define('MyWindow', {
        extend: 'Ext.window.Window',
        layout: 'fit',
        title: 'Foo',
    
        initComponent: function(){
            this.items = {
                xtype: 'grid',
                store: this.store,
                columns: this.columns    
            };
            this.callParent();
        }
    });
    
    Ext.onReady(function(){
        new MyWindow({
            width: 200,
            height: 200,
            autoShow: true,
            store: {
                fields: ['name'],
                data: [{
                    name: 'Name 1'
                }]
            },
            columns: [{
                dataIndex: 'name',
                text: 'Name'
            }]
        });
    });
    

    【讨论】:

    • 感谢您,这非常有帮助。只要我关心的是商店和列配置,它就可以完美运行。不幸的是,如果我尝试配置网格以进行编辑(设置 selType 和插件),则会收到错误消息“无法读取未定义的属性 'selModel'”。未定义的变量是网格的视图。我也尝试将视图和 selModel 复制下来,但它变得 a) 太复杂 b) 无论如何都无法工作。我真的很想要一种复制所有东西的方法,包括函数。出于所有意图和目的,包含的网格是用户配置的网格...
    • 另一种方法可能是可重用组件是一个网格(扩展 Ext.grid.Panel),但在某些时候(initComponent?)它会将自己从其父容器中移除,将自己放入一个新容器中,并将该容器添加回父级的相同位置。像这样的东西可以吗?
    猜你喜欢
    • 2020-02-04
    • 2019-04-02
    • 2018-08-03
    • 2019-02-17
    • 2020-08-21
    • 1970-01-01
    • 2020-09-01
    • 2020-03-30
    • 2020-07-23
    相关资源
    最近更新 更多