2015-08-25 5 views
2

Мне очень трудно понять, как получить доступ к фактическому экземпляру виртуального хранилища для компонента, например, ComboBox или Grid. Похоже, что когда вы используете свой метод getStore, он возвращает другой экземпляр.ExtJS 5: Доступ к связанному хранилищу в компоненте

В моем example у меня есть пользовательский класс сетки, и в его initComponent я хочу добавить загрузчика загрузки. К сожалению, прослушиватель нагрузки никогда не попадает, но прослушиватель загрузки загруженного хранилища. Вы можете видеть, что слушатель настраивается до загрузки магазина, так что это не проблема. Похоже, что экземпляр store в initComponent является хранилищем памяти, поэтому экземпляр связанного хранилища не синхронизируется с компонентом на данный момент.

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

Может ли кто-нибудь объяснить мне, почему мой пользовательский загрузочный слушатель класса сетки не получает удар, и что я могу сделать, чтобы исправить это? Могу ли я каким-либо образом получить доступ к экземпляру связанного хранилища?

Ext.application({ 
    name: 'Fiddle', 

    launch: function() { 
    Ext.define('MyGrid', { 
     extend: 'Ext.grid.Panel', 
     xtype: 'myGrid', 
     initComponent: function() { 
     alert('initComponent') 
     this.callParent(); 
     this.getStore().on('load', this.onLoad, this); 
     }, 
     onLoad: function() { 
     alert('grid store loaded'); 
     } 
    }); 
    Ext.define('MyViewController', { 
     extend: 'Ext.app.ViewController', 
     alias: 'controller.myview', 
     onLoadBoundStore: function() { 
     alert('loaded bound'); 
     } 
    }) 
    Ext.define('MyViewModel', { 
     extend: 'Ext.app.ViewModel', 
     alias: 'viewmodel.myview', 
     stores: { 
     myStore: { 
      fields: ['name', 'value'], 
      autoLoad: true, 
      proxy: { 
      type: 'ajax', 
      url: 'data1.json', 
      reader: { 
       type: 'json' 
      } 
      }, 
      listeners: { 
      load: 'onLoadBoundStore' 
      } 
     } 
     } 
    }); 
    Ext.define('MyView', { 
     extend: 'Ext.form.Panel', 
     renderTo: Ext.getBody(), 
     controller: 'myview', 
     viewModel: { 
     type: 'myview' 
     }, 
     items: [{ 
     title: 'blah', 
     xtype: 'myGrid', 
     reference: 'myComboBox', 
     bind: { 
      store: '{myStore}' 
     }, 
     columns: [{ 
      text: 'Name', 
      dataIndex: 'name' 
     }, { 
      text: 'Value', 
      dataIndex: 'value' 
     }] 
     }] 
    }); 
    Ext.create('MyView') 
    } 
}); 

ответ

3

Может кто-нибудь объяснить мне, почему слушатель нагрузки моего пользовательского класса GRID является не получить удар, и что я могу сделать, чтобы исправить это?

Вы изначально не предоставление какого-либо магазина сетка (опция store конфигурации является требуется, кстати). Таким образом, сетка создает свой собственный, пустой магазин в закодированном here:

store = me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store'); 

Это пустой магазин является тот, который получает прилагается ваш onLoad слушателя. Он не попадает, потому что магазин никогда не загружается.

Могу ли я каким-либо образом получить доступ к экземпляру связанного магазина?

Да, используйте:

this.lookupViewModel().getStore('myStore') 

Вы можете прикрепить слушателя к связанному магазина вместо пустого и увидеть разницу. Пустое хранилище сетки в конечном итоге заменяется на связанный (вот почему вы видите данные в сетке, в конце концов), но это происходит послеinitComponent. Вы можете отслеживать момент установки связанного хранилища в сетку, переопределяя метод setStore.

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

Поскольку вы используете MVVC, рекомендуется придерживаться шаблона и сохранять представления, отражающие только аспекты взгляда.Слушатели должны быть объявлены и обработаны в контроллерах (даже не в моделях вида, как в вашем примере). В противном случае, если вы продолжаете придерживаться стиля pre Ext JS 5 и ставите динамический материал во взглядах (т. Е. Сетка в вашем случае), нет смысла использовать MVVC.

+0

Вау, большое спасибо! Вы дали мне еще несколько последующих вопросов ... 'параметр конфигурации магазина требуется по правильному пути, но я привязываю магазин, так что вы фактически объявляете магазин, даже если вы привязываете его? Это кажется излишним. – incutonez

+0

'Слушатели должны быть объявлены и обработаны в контроллерах (даже не в моделях вида, как в вашем примере). Итак, по этой логике вы говорите, что я не должен объявлять слушателей в представлении? Я думаю, что добавляет слишком много раздувания в контроллере ... тогда я должен искать все ссылки и добавлять слушателей ... это кажется немного ненужным, учитывая, что у меня есть удобный способ добавления слушателей. – incutonez

+0

'this.lookupViewModel()' - очень интересная часть знаний ... с учетом 'this.getViewModel()' возвращает null. Похоже, последний является удобным getter для текущего уровня viewModel, а затем lookupViewModel идет до тех пор, пока не найдет один, который будет унаследованным. – incutonez

1

Это настолько невероятно взломанно, что я даже не хочу публиковать его в качестве ответа, но я собираюсь только ради потомства. Основываясь на ответе Дрейка, я понял, как получить мой магазин, используя то, что было передано в первоначальной конфигурации моего класса сетки. Связывание приходит с фигурными скобками, поэтому я делаю на нем replace. Как я уже сказал, это, вероятно, никогда не следует использовать, но это что-то.

initComponent: function() { 
    var store = this.lookupViewModel().getStore(this.config.bind.store.replace(/[{}]/g, '')); 
    store.on('load', this.onLoad, this); 
    this.callParent(); 
}, 
0

Просто добавить еще один вариант к соединению, вы можете слушать reconfigure события на сетке, так как это то, что срабатывает после связывания магазина является полным ... так что-то, как это будет работать:

Ext.application({ 
    name: 'Fiddle', 

    launch: function() { 
    Ext.define('MyGrid', { 
     extend: 'Ext.grid.Panel', 
     xtype: 'myGrid', 
     initComponent: function() { 
     alert('initComponent') 
     this.on('reconfigure', this.onReconfigureGrid, this); 
     this.callParent(); 
     }, 
     onReconfigureGrid: function(grid, store, columns, oldStore, oldColumns, eOpts) { 
     store.on('load', this.onLoad, this); 
     }, 
     onLoad: function() { 
     alert('grid store loaded'); 
     } 
    }); 
    Ext.define('MyViewController', { 
     extend: 'Ext.app.ViewController', 
     alias: 'controller.myview', 
     onLoadBoundStore: function() { 
     alert('loaded bound'); 
     } 
    }) 
    Ext.define('MyViewModel', { 
     extend: 'Ext.app.ViewModel', 
     alias: 'viewmodel.myview', 
     stores: { 
     myStore: { 
      fields: ['name', 'value'], 
      autoLoad: true, 
      proxy: { 
      type: 'ajax', 
      url: 'data1.json', 
      reader: { 
       type: 'json' 
      } 
      }, 
      listeners: { 
      load: 'onLoadBoundStore' 
      } 
     } 
     } 
    }); 
    Ext.define('MyView', { 
     extend: 'Ext.form.Panel', 
     renderTo: Ext.getBody(), 
     controller: 'myview', 
     viewModel: { 
     type: 'myview' 
     }, 
     items: [{ 
     title: 'blah', 
     xtype: 'myGrid', 
     reference: 'myComboBox', 
     bind: { 
      store: '{myStore}' 
     }, 
     columns: [{ 
      text: 'Name', 
      dataIndex: 'name' 
     }, { 
      text: 'Value', 
      dataIndex: 'value' 
     }] 
     }] 
    }); 
    Ext.create('MyView'); 
    } 
}); 
Смежные вопросы