2015-10-13 1 views
0

Я уверен, что здесь кое-что отсутствует, и я просто не вижу, что это такое.Похоже, что ViewModel сохраняется после того, как его вид разрушен в extjs

У меня есть демонстрационный проект, который я строю в extjs 6. В нем у меня есть сетка предметов инвентаря.

Ext.define("InventoryDemo.view.inventory.list.Inventory",{ 
    extend: "Ext.container.Container", 
    xtype: 'inventory', 

    requires: [ 
     "InventoryDemo.view.inventory.list.InventoryController", 
     "InventoryDemo.view.inventory.list.InventoryModel" 
    ], 

    controller: "inventory-inventory", 
    viewModel: { 
     type: "inventory-inventory" 
    }, 
    closable: true, 

    listeners:{ 
     refreshList: 'onRefreshList' 
    }, 


    layout:{ 
     type: 'hbox', 
     align: 'stretch' 
    }, 
    items:[ 
     { 
      xtype: 'grid', 
      flex: 1, 

      tbar:[ 
       {xtype: 'button', text: 'New Item', handler: 'newInventoryItem'} 
      ], 

      bind:{ 
       store: '{inventory}' 
      }, 

      listeners:{ 
       itemclick: 'showDetails' 
      }, 

      columns:[ 
       { text: 'Name', dataIndex: 'name', flex: 1 }, 
       { text: 'Price', dataIndex: 'price' }, 
       { text: 'Active', dataIndex: 'active' }, 
      ] 
     } 
    ] 
}); 

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

Вот контроллер в списке в:

Ext.define('InventoryDemo.view.inventory.list.InventoryController', { 
    extend: 'Ext.app.ViewController', 
    alias: 'controller.inventory-inventory', 

    config:{ 
     // holds the newly created detail panel 
     detailsPanel: null 
    }, 

    showDetails: function (grid, record, item, index, e, eOpts){ 
     this.createDetailsPanel(); 
     this.addTitleToDetailsPanel(record.get('name')); 

     // This creates the link in the new detail panel's viewmodel for the 
     // selected record. We specifically do NOT do this in the 
     // `newInventoryItem`. 
     details.getViewModel().linkTo('inventoryitem', record); 

     this.addDetailsPanelToView(); 
    }, 

    newInventoryItem: function (button, e){ 
     this.createDetailsPanel(); 
     this.addTitleToDetailsPanel('New Item'); 

     // I thought that because the previous panel was destroyed during the 
     // `createDetailsPanel` method any previously linked record would not 
     // be linked to the new detail panel created and that not linking here 
     // would give me an empty detail panel. 
     this.addDetailsPanelToView(); 
    }, 


    createDetailsPanel: function(){ 
     if(this.getDetailsPanel() !== null){ 
      // I'm destroying any previous view here which, as I understand, 
      // would also destroy the the associated ViewController and ViewModel 
      // which would also kill any links to the viewmodel 
      this.getDetailsPanel().destroy(); 
     } 

     details = Ext.create('InventoryDemo.view.inventory.details.Inventory',{ 
      session: true, 
      listeners:{ 
       refreshList: 'onRefreshList' 
      } 
     }); 
     this.setDetailsPanel(details); 
    }, 

    addDetailsPanelToView: function(){ 
     this.getView().add(this.getDetailsPanel()); 
    }, 

    addTitleToDetailsPanel: function (title){ 
     this.getDetailsPanel().setTitle("<h3>" + title + "</h3>"); 
    }, 

    onRefreshList: function(){ 
     this.getViewModel().get('inventory').load(); 
    } 
}); 

ПОДРОБНО.Подробнее панель создается выглядит следующим образом:

Ext.define("InventoryDemo.view.inventory.details.Inventory",{ 
    extend: "Ext.form.Panel", 

    requires: [ 
     "InventoryDemo.view.inventory.details.InventoryController", 
     "InventoryDemo.view.inventory.details.InventoryModel" 
    ], 

    controller: "inventory-details-inventory", 
    viewModel: { 
     type: "inventory-details-inventory" 
    }, 

    flex: 1, 
    closable: true, 
    bodyPadding: 10, 
    reference: 'inventorydetails', 
    defaults:{ 
     layout: 'anchor', 
     anchor: '50%' 
    }, 
    dockedItems:[ 
     { 
      xtype: 'toolbar', 
      dock: 'bottom', 
      ui: 'footer', 
      items:[ 
       {xtype: 'button', text: 'Update', handler: 'updateRecord'}, 
       {xtype: 'button', text: 'Delete', handler: 'deleteRecord'} 
      ] 
     } 
    ], 

    items:[ 
     { 
      xtype: 'hiddenfield', 
      name: '_method', 
      value: 'PUT' 
     }, 
     { 
      xtype: 'fieldset', 
      title: 'IDs', 
      collapsible: true, 
      defaults:{ 
       xtype: 'textfield' 
      }, 
      items:[ 
       { 
        name: 'id', 
        fieldLabel: 'ID', 
        readOnly: true, 
        bind: '{inventoryitem.id}' 
       }, 
       { 
        name: 'brand_id', 
        fieldLabel: 'Brand ID', 
        readOnly: true, 
        bind: '{inventoryitem.brand_id}' 
       } 
      ] 
     }, 
     { 
      xtype: 'fieldset', 
      title: 'Details', 
      defaults:{ 
       xtype: 'textfield' 
      }, 
      items:[ 
       { 
        name: 'name', 
        fieldLabel: 'Name', 
        bind: '{inventoryitem.name}' 
       }, 
       { 
        name: 'price', 
        fieldLabel: 'Price', 
        bind: '{inventoryitem.price}' 
       } 
      ] 
     } 
    ] 

}); 

Проблема, что я бегу в, если я нажимаю на строке, чтобы просмотреть его детали (который работает), а затем нажмите кнопку New Item, запись, которая была загружена на предыдущей панели подробностей, по-прежнему загружается на новую панель подробностей.

Если я нажму кнопку New Item, сначала я получу пустую форму, в которой я собираюсь, и если я выберу разные строки элементов, каждая из записей из выбранной строки будет правильно загружаться в панель подробностей (это не та ситуация, когда запись из первой строки «застряли» в панели подробностей), но как только я выберу строку, кнопка New Item даст мне только формы с ранее загруженной записью.

Есть ли что-то, что могло бы сделать ссылку на viewmodel, сохраняться между уничтожением и созданием двух отдельных представлений/viewmodels/viewcontrollers (или есть недостаток в моей логике контроллера, который я просто не вижу)?

ответ

0

Если единственное, что вам нужно в представлении деталиModel - это единственное свойство, к которому вы пытаетесь установить ссылку, не используйте автономную viewModel для детализации вообще.

Когда ваша панель сведений находится в элементах вашего изображения inventory, у нее фактически есть естественный доступ к представлению видаModel (detailPanel.lookupViewModel() вернет единственный ближайший viewModel в иерархии дерева компонентов). Привязки тоже должны работать.

Однако, если вам нужна отдельная панель просмотра для панели подробностей, вы можете создать подробный вид с помощью ad-hoc viewModel config, который будет объединен в viewModel детали при создании экземпляра.

Вид:

Ext.define('APP.view.TheView',{ 
    extend: "Ext.container.Container", 
    alias: 'widget.theView', 

    controller: 'theView', 
    viewModel: { type: 'theView' }, 

    config: { 
     detailConfig: { xtype: 'theDetail', reference: 'detail' } 
    }, 

    items: ... 
}; 

ViewController вида по:

Ext.define('APP.controller.TheView',{ 
    extend: "Ext.app.ViewController", 
    alias: 'controller.theView', 

    onOpenDetail: function(){ 

     var detail = this.lookupReference('detail'); 

     if(!detail){ 

      var view = this.getView(), 
       detailConfig = view.getDetailConfig(), 
       theProperty = this.getViewModel().get('theProperty'); 

      detailConfig = Ext.apply({ 
       viewModel: { 
        // This actually gets correctly merged with whatever there is 
        // in the viewModel configuration of the detail 
        data: { theProperty: theProperty } 
       } 
      }, detailConfig)); 

      detail = view.add(detailConfig); 
     } 

     // Do something with the detail instance 
    } 
}; 

И деталь:

Ext.define('APP.view.TheDetail',{ 
    extend: "Ext.panel.Panel", 
    alias: 'widget.theDetail', 

    controller: 'theDetail', 
    viewModel: { type: 'theDetail' }, 

    items: ... 
}; 

Надеется, что это помогает мало! :-)

Смежные вопросы