ExtJS 4 - Повторное использование компонентов в архитектуре MVC - PullRequest
2 голосов
/ 24 мая 2011

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

Но если я загружаю данные в определенное окно, я загружаю те же данные во все другие открытые окна.

Ext.define('Cc.view.absence.Grid', {
  extend: 'Ext.grid.Panel',
  alias: 'widget.absencegrid',

  border:false,

  initComponent: function() {
    Ext.apply(this, {
      store: Ext.create('Ext.data.Store', {
        model: 'Cc.model.Absence',
        autoLoad: false,
        proxy: {
          type: 'ajax',
          reader: {
            type: 'json'
          }
        }
      }),
      columns: [
        {header: 'Du', dataIndex: 'startdate', flex: 3, renderer: this.formatDate},
        {header: 'Au', dataIndex: 'enddate', flex: 3, renderer: this.formatDate},
        {header: 'Exercice', dataIndex: 'year', align: 'center', flex: 1},
        {header: 'Statut', xtype:'templatecolumn', tpl:'<img src="../images/status-{statusid}.png" alt="{status}" title="{status}" />', align: 'center', flex: 1},
        {header: 'Type d\'absence', dataIndex: 'absencetype', align: 'center', flex: 2},
        {header: 'Commentaires', dataIndex: 'comment', flex: 6}
      ],
      dockedItems: [{
        xtype: 'toolbar',
        dock: 'top',
        items: [
          { xtype: 'tbfill'},
          { xtype: 'button', text: 'Rafraichir', action: 'refresh', iconCls: 'item-rafraichir' }
        ]
      }]
    });

    this.callParent(arguments);
  },

  formatDate: function(date) {
    if (!date) {
      return '';
    }
    return Ext.Date.format(date, 'l d F Y - H:i');
  }

});

мой контроллер:

Ext.define('Cc.controller.Absences', {
  extend: 'Ext.app.Controller',

  models: ['Absence', 'AbsenceHistory'],

  views: [],

  refs: [
    { ref: 'navigation', selector: 'navigation' },
    { ref: 'tabPanel', selector: 'tabpanel' },
    { ref: 'absencePanel', selector: 'absencepanel' },
    { ref: 'refreshButton', selector: 'absencepanel button[action=refresh]'},
    { ref: 'absenceGrid', selector: 'absencegrid' },
    { ref: 'absenceHistory', selector: 'absencehistory' },
  ],

  init: function() {
    this.control({
      'absencepanel button[action=refresh]': {
        click: this.onClickRefreshButton
      },
      'absencegrid': {
        selectionchange: this.viewHistory
      },
      'absencegrid > tableview': {
        refresh: this.selectAbsence
      },
    });
  },

  selectAbsence: function(view) {
    var first = this.getAbsenceGrid().getStore().getAt(0);
    if (first) {
      view.getSelectionModel().select(first);
    }
  },

  viewHistory: function(grid, absences) {
    var absence = absences[0],
      store = this.getAbsenceHistory().getGrid().getStore();
    if(absence.get('id')){
      store.getProxy().url = '/absence/' + absence.get('id') +'/history';
      store.load();
    }
  },

  onClickRefreshButton: function(view, record, item, index, e){
    var store = this.getAbsenceGrid().getStore();
    store.load();
  },
});

другой контроллер, который создает только один случай отсутствия. Панель:

Ext.define('Cc.controller.Tools', {
  extend: 'Ext.app.Controller',

  stores: ['Tools', 'User' ],

  models: ['Tool'],

  views: [],

  refs: [
    { ref: 'navigation', selector: 'navigation' },
    { ref: 'tabPanel', selector: 'tabpanel' },
    { ref: 'toolList', selector: 'toollist' },
    { ref: 'toolData', selector: 'toollist dataview' }
  ],

  init: function() {
    this.control({
      'toollist dataview': {
        itemclick: this.loadTab
      },
    });
  },

  onLaunch: function() {
    var dataview = this.getToolData(),
        store = this.getToolsStore();

    dataview.bindStore(store);
  },

  loadTab: function(view, record, item, index, e){
    var tabPanel = this.getTabPanel();
    switch (record.get('tab')) {
      case 'absences':
        if(Ext.getCmp('absence-panel')){
          tabPanel.setActiveTab(Ext.getCmp('absence-panel'));
        }
        else {
          var panel = Ext.create('Cc.view.absence.Panel',{
            id: 'absence-panel'
          }),
              store = panel.getGrid().getStore();
          panel.enable();
          tabPanel.add(panel);
          tabPanel.setActiveTab(panel);
          store.getProxy().url = '/person/' + this.getUserId() +'/absences';
          store.load();
        }
      break;

      default: 
      break;
    }
  },

  getUserId: function(){
    var userStore = this.getUserStore();
    var id = userStore.first().get('id')
    return id;
  }
});

другой контроллер, который создает много случаев отсутствия. Панель:

Ext.define('Cc.controller.Agents', {
  extend: 'Ext.app.Controller',

  stores: ['Agents'],

  models: ['Agent', 'Absence', 'AbsenceHistory'],

  views: ['agent.List', 'agent.Window', 'absence.Panel', 'absence.Grid', 'absence.History'],
  refs: [
    { ref: 'agentList', selector: 'agentlist' },
    { ref: 'agentData', selector: 'agentlist dataview' },
    { ref: 'agentWindow', selector: 'agentwindow' },
  ],

  init: function() {
    this.control({
      'agentlist dataview':{
        itemclick: this.loadWindow
      },
    });
  },

  onLaunch: function() {
    var dataview = this.getAgentData(),
        store = this.getAgentsStore();
    dataview.bindStore(store);
  },

  loadWindow: function(view, record, item, index, e){
    if(!Ext.getCmp('agent-window'+record.get('id'))){
      var window = Ext.create('Cc.view.agent.Window', {
        title: 'À propos de '+record.get('firstname')+' '+record.get('lastname'),
        id: 'agent-window'+record.get('id')
      }),
          tabPanel = window.getTabPanel();
          absencePanel = window.getAbsencePanel();
          store = absencePanel.getGrid().getStore();

      absencePanel.enable();
      tabPanel.add(absencePanel);
      tabPanel.setActiveTab(absencePanel);
      store.getProxy().url = '/person/' + record.get('id') +'/absences';
      store.load();
    }
    Ext.getCmp('agent-window'+record.get('id')).show();
  }
});

и отсутствие. Вид панели, контейнер отсутствия. Сетка:

Ext.define('Cc.view.absence.Panel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.absencepanel',

  title: 'Mes absences',
  iconCls: 'item-outils',
  closable: true,
  border: false,
  disabled: true,
  layout: 'border',

  initComponent: function() {
    this.grid = Ext.create('Cc.view.absence.Grid', {
      region: 'center'
    });
    this.history = Ext.create('Cc.view.absence.History', {
      region: 'south',
      height: '25%'
    });
        Ext.apply(this, {
      items: [
        this.grid,
        this.history
      ]
    });

        this.callParent(arguments);
    },

  getGrid: function(){
    return this.grid;
  },

  getHistory: function(){
    return this.history;
  }
});

1 Ответ

5 голосов
/ 24 мая 2011

Да. Вот более подробное объяснение того, что я делаю. Я надеюсь, что вы прочитали форум полностью. Есть еще одна информация, которая нам не ясна. Именно так и используется свойство «stores» в контроллере. ИМХО, команда Сенчи должна объяснить MVC гораздо более подробно со сложными примерами.

Да, то, что вы недавно опубликовали, правильно. когда вы создадите новый вид, создайте новый экземпляр магазина! Теперь из дискуссий на форуме люди спорят о MVC. Я бы определенно пошел с Штеффенк . То, что мы делаем здесь, это введение нового экземпляра магазина на мой взгляд. И я игнорирую свойство stores контроллера.

Вот пример:

Это мой взгляд. Это панель (с информацией профиля пользователя), которую я отображаю на своей вкладке:

Ext.define('Dir.view.profile.View' ,{
    extend: 'Ext.panel.Panel',
    alias : 'widget.profileview',
    title : 'Profile',
    profileId: 1,   // default and dummy value
    initComponent: function() {

        // configure necessary stuff, I access my store etc here..       
        // console.log(this.profileStore);
        this.callParent(arguments);         
    },
    // Other view methods goes here
});

Теперь посмотрите на мой контроллер:

Ext.define('Dir.controller.Profile', {
    extend: 'Ext.app.Controller',
    //stores: ['Profile'],   --> Note that I am NOT using this!
    refs: [     
        {ref:'cp',selector: 'centerpane'}
    ],
    views: ['profile.View'],
    init: function() {
        // Do your init tasks if required
    },  
    displayProfile: function(selectedId) {

            // create a new store.. pass your config, proxy url etc..
        var store = Ext.create('Dir.store.Profile',{profileId: selectedId});

        console.log('Display Profile for ID ' + selectedId);    

        // Create instance of my view and pass the new store
        var view = Ext.widget('profileview',{profileId: selectedId,profileStore: store});

        // Add my new view to centeral panel and display it...
        this.getCp().add(view);
        this.getCp().setActiveTab(view);
    }
});

Мой displayProfile() вызывается из некоторых прослушивателей событий (Меню, Дерево и т. Д.) И передает идентификатор. Мой контроллер использует этот идентификатор для настройки нового магазина и просмотра. Я надеюсь, что приведенный выше код дает вам четкое представление о том, что я сказал вчера.

В вашем контроллере вам нужно будет добавить Ext.require('Dir.store.Profile');, чтобы ExtJS знал, что у вас есть такой магазин. Это потому, что мы не используем свойство stores.

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


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

...