2013-05-12 46 views
6

使用ExtJS的4.2瞭解商店模型是如何引用/ loade /在ExtJS的4.2實例MVC模式

我看了很多文檔,谷歌,論壇試圖瞭解如何組成部分負荷,在那裏他們將如商店,模型,但仍然困惑。

這是我試圖讓工作

應用說明

主菜單,聯繫人,項目,人員等等等等,應用程序首次加載顯示靜態非數據驅動的,然後用點擊一個例子在顯示帶有聯繫人列表的網格的聯繫人上。用戶然後點擊聯繫人行並顯示彈出編輯視圖。

在contactsView中聯繫人被加載到表單中,此外表單還有一個加載ContactTypes存儲的組合框。聯繫人類型應設置爲該聯繫人記錄的聯繫人類型值。

考慮到這是一個很大的應用程序,這樣做的常見方法是什麼?我只想在需要時加載數據,即顯示視圖。

下面是我的一些混亂的

1)可以定義大家控制器,存儲,模型,在應用程序配置意見,但隨後一切都加載無論你看什麼網頁。另外,如果在商店中有autoLoad:true,那麼即使您沒有查看特定視圖,也會調用所有商店的數據庫。

2)當您在控制器的商店或模型屬性中指定商店或模型時,具體做什麼?它只是讓你輕鬆地引用商店,但實際上並沒有創建它,或者創建它,還是隻是爲了方便而設置getter和setter函數。例如,如果我在控制器的store屬性中指定商店並且autoLoad爲true,則所有數據都將被加載而不需要執行任何其他操作。但我真正想要的是,只有當我點擊聯繫人並顯示列表視圖時,纔會加載該商店。所以我設置了autoLoad:false,並在我的列表函數中手動獲取使用this.getStore('Contacts')的商店。這工作正常,但什麼是使用控制器的商店和模型數組屬性的目的。我在調試器中看到,如果我不使用store/model屬性,則會爲這些js文件獲取請求。

對不起,我知道這是很多,但它是我非常困惑,並一直努力了一段時間。

3)最後,我只有在通過設置autoLoad單擊「聯繫人」按鈕加載聯繫網格時:false並手動加載。現在,當用戶點擊編輯記錄加載罰款,但我怎麼得到組合框加載,然後選擇正確的值。我認爲我的問題的一部分是瞭解商店模型如何加載和實例化。在我的組合框存儲屬性中,我指定了ContactType作爲存儲,但是我得到的錯誤存儲未定義,因此js文件未加載或未實例化存儲。

這是我的代碼到目前爲止。

應用程序代碼

Ext.Loader.setConfig({ 
    enabled: true, 
    paths: { 
     'Ext.ux': "lib/extux", 
     'Wakanda': "lib/extux/wakanda" 
    } 
}); 
Ext.application({ 
    name: 'SimplyFundraising', 
    autoCreateViewport: true, 

    requires: ['Ext.ux.Router', // Require the UX 
     'Wakanda.model'], 

    controllers: ['Contacts'], 
}); 

聯繫控制器

Ext.define('SimplyFundraising.controller.Contacts', { 
    extend: 'Ext.app.Controller', 


    views: ['contacts.List', 'contacts.Edit'], 
    init: function() { 
     this.control({ 
      'contactslist': { 
       itemdblclick: this.editContact, 
       removeitem: this.removeContact 
      }, 
      'contactslist > toolbar > button[action=create]': { 
       click: this.onCreateContact 
      }, 
      // 'contactsadd button[action=save]': { 
      // click: this.doCreateContact 
      // }, 
      'contactsedit button[action=save]': { 
       click: this.updateContact 
      } 
     }); 
    }, 
    list: function() { 

     var mystore = this.getStore('Contacts') 
     mystore.load(); 
// mystore.proxy.extraParams = { $expand: 'ContactType'}; 
//  var User = this.getContactModel(); 
//  User.load(258, { 
//   success: function (user) { 
//    console.log("Loaded user 258: " + user.get('lastName')); 
//   } 
//  }); 
    }, 
    editContact: function (grid, record) { 
     var view = Ext.widget('contactsedit'); 
     view.down('form').loadRecord(record); 
     this.addnew = false 
    }, 
    removeContact: function (Contact) { 
     Ext.Msg.confirm('Remove Contact ' + Contact.data.lastName, 'Are you sure?', function (button) { 
      if (button == 'yes') { 
       this.getContactsStore().remove(Contact); 
      } 
     }, this); 
    }, 
    onCreateContact: function() { 
     var view = Ext.widget('contactsedit'); 
     this.addnew = true 
    }, 
    // doCreateContact: function (button) { 
    // var win = button.up('window'), 
    // form = win.down('form'), 
    // values = form.getValues(), 
    // store = this.getContactsStore(); 
    // if (form.getForm().isValid()) { 
    // store.add(values); 
    // win.close(); 
    // } 
    // }, 
    updateContact: function (button) { 
     var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(), store = this.getContactsStore(); 
     if (form.getForm().isValid()) { 
      if (this.addnew == true) { 
       store.add(values); 
      } else { 
       record.set(values); 
      } 
      win.close(); 
     } 
    } 
}); 

聯繫人中,查看列表

Ext.define('SimplyFundraising.view.contacts.List', { 
    extend : 'Ext.grid.Panel', 
    xtype : 'contactslist', 
    title : 'All Contacts', 
    store : 'Contacts', 
    autoHeight: true, 
    autoScroll : true, 
    viewConfig : { 
     loadMask : true 
    }, 
    initComponent : function() { 
     this.tbar = [{ 
      text : 'Create Contact', 
      action : 'create' 
     }]; 
     this.columns = [{ 
      header : 'Id', 
      dataIndex : '__KEY', 
      width : 50 
     }, { 
      header : 'First Name', 
      dataIndex : 'firstName', 
      flex : 1 
     }, { 
      header : 'Middle Name', 
      dataIndex : 'middleName', 
      flex : 1 
     }, { 
      header : 'Last Name', 
      dataIndex : 'lastName', 
      flex : 1 
     }, 
     { 
      header : 'Type', 
      dataIndex : 'ContactType.name', 
      flex : 1 
     }]; 
     this.addEvents('removeitem'); 
     this.actions = { 
      removeitem : Ext.create('Ext.Action', { 
       text : 'Remove Contact', 
       handler : function() { 
        this.fireEvent('removeitem', this.getSelected()) 
       }, 
       scope : this 
      }) 
     }; 
     var contextMenu = Ext.create('Ext.menu.Menu', { 
      items : [this.actions.removeitem] 
     }); 
     this.on({ 
      itemcontextmenu : function(view, rec, node, index, e) { 
       e.stopEvent(); 
       contextMenu.showAt(e.getXY()); 
       return false; 
      } 
     }); 
     this.callParent(arguments); 
    }, 
    getSelected : function() { 
     var sm = this.getSelectionModel(); 
     var rs = sm.getSelection(); 
     if (rs.length) { 
      return rs[0]; 
     } 
     return null; 
    } 
}); 

聯繫人視圖編輯

Ext.define('SimplyFundraising.view.contacts.Edit', { 
    extend: 'Ext.window.Window', 
    xtype: 'contactsedit', 
    title: 'Edit Contacts', 
    layout: 'fit', 
    autoShow: true, 
    initComponent: function() { 
     this.items = [ 
      { 
       xtype: 'form', 
       bodyStyle: { 
        background: 'none', 
        padding: '10px', 
        border: '0' 
       }, 
       items: [ 
        { 
         xtype: 'textfield', 
         name: 'firstName', 
         allowBlank: false, 
         fieldLabel: 'Name' 
        }, 
        { 
         xtype: 'textfield', 
         name: 'lastName', 
         allowBlank: false, 
         fieldLabel: 'Last Name' 
        }, 
        { 
         xtype: 'combobox', 
         fieldLabel: 'Contact Type', 
         name: 'contactType', 
         store: 'ContactTypes', 

         displayField: 'name', 
         typeAhead: true, 
         queryMode: 'local', 
         emptyText: 'Select a type...' 
        } 
       ] 
      } 
     ]; 
     this.buttons = [ 
      { 
       text: 'Save', 
       action: 'save' 
      }, 
      { 
       text: 'Cancel', 
       scope: this, 
       handler: this.close 
      } 
     ]; 
     this.callParent(arguments); 
    } 
}); 

感謝您的幫助

+0

您是否發現問題的答案?我面臨着類似的問題,並對Ext.js MVC範例中的Stores如何管理感到困惑。 – 2013-08-21 07:07:29

+0

沒有不幸的不是。我已經停止使用Extjs,因爲不好的文檔和不好的支持,現在使用的是qooxdoo,與Extjs類似,到目前爲止我沒有任何問題,並且文檔和示例要好得多。它是完全免費的LGPL許可證,意味着您可以在商業產品中使用它。看看http://qooxdoo.org/。支持是社區驅動的,特別是與Sencha支持相比時相當不錯。而且它正在積極開發+有效的博客更新。只有瞭解構建/項目創建的初始設置問題。 – dan 2013-08-21 10:24:59

回答

2

不要錯過ExtJs。我知道,這可能是一個痛苦...

對於你的問題,我解決了這個辦法:

我有一個網格,頁面意大利的直轄市。我想按國家,地區和省進行過濾,因此我將三個組合框放在停靠的容器上。在控制器我有:

 ,init : function (application) { 
     this.control({ 
      ,"#municipalitiesGrid": { afterrender: this.onMunicipalitiesGridAfterRender } 
     }); 
     } 
,onMunicipalitiesGridAfterRender: function(grid, opts) { 
    console.info('GVD.controller.Geo->onMunicipalitiesGridAfterRender'); 
    var store = grid.getStore(), 
     comboCountriesMunicipalities = this.getComboCountriesMunicipalities(), 
     storeCountries = comboCountriesMunicipalities.getStore(), 
     comboRegionsMunicipalities = this.getComboRegionsMunicipalities(), 
     storeRegions = comboRegionsMunicipalities.getStore(), 
     comboProvincesMunicipalities = this.getComboProvincesMunicipalities(), 
     storeProvinces = comboProvincesMunicipalities.getStore(); 

     store.clearFilter(true); 
     storeCountries.clearFilter(true); 
     storeRegions.clearFilter(true); 
     storeProvinces.clearFilter(true); 

     storeRegions.filter("idCountry", 114); // 114 = Italia 
     storeProvinces.filter("idRegion",8); // 8 = Emilia Romagna 
     store.filter("idProvince", 37);  // 37 = Bologna 

     storeCountries.load({ 
     scope: this, 
    callback: function(records, operation, success) { 
     storeRegions.load({ 
     scope: this, 
     callback: function(records, operation, success) { 
      storeProvinces.load({ 
      scope: this, 
     callback: function(records, operation, success) { 
      store.load({ 
      scope: this, 
      callback: function(records, operation, success) { 
       comboCountriesMunicipalities.setValue(114); // 114 = Italia 
       comboRegionsMunicipalities.setValue(8);  // 8 = Emilia Romagna 
       comboProvincesMunicipalities.setValue(37); // 37 = Bologna  
      } 
      }); 
     } 
      }); 
     } 
     }); 
     } 
     }); 
} 

在控制器,當然,我有其他偵聽組合框的「選擇」事件,所以可以過濾和根據所選擇的值重新加載組合。

繼MVC行話,我的店都與此類似:

Ext.define('GVD.store.Municipalities', { 
    extend: 'Ext.data.Store' 
    ,constructor: function(cfg) { 
     console.info('GVD.store.Municipalities->constructor'); 
     var me = this; 
     cfg = cfg || {}; 
     me.callParent([Ext.apply({ 
      autoLoad: false 
      ,autoSync: true 
      ,model: 'GVD.model.Municipalities' 
      ,pageSize: 20 
     }, cfg)]); 
    } 
}); 

和模式類似於:

Ext.define('GVD.model.Municipalities', { 
    extend: 'Ext.data.Model', 

    fields: [ 
     { name: 'id',    type: 'int'   }, 
     { name: 'idIstat',  type: 'int'   }, 
     { name: 'idCountry',  type: 'int'   }, 
     { name: 'idRegion',  type: 'int'   }, 
     { name: 'idProvince',  type: 'int'   }, 
     { name: 'name',   type: 'string'  }, 
     { name: 'chief_town',  type: 'boolean'  }, 
     { name: 'altitude_zone', type: 'int'   }, 
     { name: 'altitude',  type: 'int'   }, 
     { name: 'coastal',  type: 'int'   }, 
     { name: 'mountain',  type: 'int'   }, 
     { name: 'surface',  type: 'double'  }, 
     { name: 'residents',  type: 'int'   }, 
     { name: 'icon',   type: 'string'  } 
    ] 
    ,proxy: { 
     api: { 
      create: 'Municipalities.create' 
      ,destroy: 'Municipalities.destroy' 
      ,read: 'Municipalities.read' 
      ,update: 'Municipalities.update' 
     } 
     ,reader: { 
      root: 'data' 
      ,totalProperty: 'totalCount' 
      ,type: 'json' 
     } 
     ,type: 'direct' 
    } 
}); 

而在我的網格引用是這樣的:

Ext.define('GVD.view.system.geo.ListMunicipalities', { 
    autoScroll: true 
    ,constrain: true 
    ,dockedItems: [{ 
     xtype: 'topBar' 
    },{ 
     items: [{ 
       allowBlank: true 
       ,fieldLabel: 'Nazione' 
       ,flex: 1 
       ,id: 'comboCountriesMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/countries/16/{icon}16.gif" align="left">&nbsp;&nbsp;{italianName}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Countries', {pageSize: 999}) 
       ,xtype: 'comboCountries'  
     },{ 
       allowBlank: true 
       ,fieldLabel: 'Regione' 
       ,flex: 1 
       ,id: 'comboRegionsMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/regions/16/{icon}16.gif" align="left">&nbsp;&nbsp;{name}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Regions', {pageSize: 999}) 
       ,xtype: 'comboRegions' 
     },{ 
       allowBlank: true 
       ,fieldLabel: 'Provincia' 
       ,flex: 1 
       ,id: 'comboProvincesMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/provinces/16/{icon}16.gif" align="left">&nbsp;&nbsp;{name}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Provinces', {pageSize: 999}) 
       ,xtype: 'comboProvinces'  
     }] 
     ,layout: 'hbox' 
     ,xtype: 'container' 
    }, { 
     dock: 'bottom' 
     ,itemId: 'municipalitiesPagingToolbar' 
     ,store: 'Municipalities' 
     ,xtype: 'pagingToolBar' 
    }] 
    ,extend: 'Ext.window.Window' 
    ,height: 400 
    ,icon: 'resources/images/GVD/municipalities16.png' 
    ,id: 'listMunicipalities' 
    ,items: [{ 
     columns: [{ 
      xtype: 'rownumberer' 
     },{ 
      align: 'right' 
      ,dataIndex: 'id' 
      ,format: '000' 
      ,renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { 
       return '<img src="resources/images/municipalities/16/'+record.data.icon+'16.gif" align="left">&nbsp;&nbsp;'+record.data.id; 
      } 
      ,text: 'Id' 
      ,width: 70 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'idIstat' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '000000000' 
      ,text: 'Istat' 
      ,width: 80 
      ,xtype: 'numbercolumn'   
     },{ 
      dataIndex: 'name' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'string' } 
      ,flex: 1 
      ,text: 'Denominazione' 
      ,xtype: 'gridcolumn' 
     },{ 
      dataIndex: 'chief_town' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,text: 'Capoluogo' 
      ,width: 40 
      ,xtype: 'numbercolumn'  
      },{ 
      dataIndex: 'altitude_zone' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Zona alt.' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'altitude' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0000' 
      ,text: 'Altitudine' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'coastal' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Costiero' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'mountain' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Montano' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'surface' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '000,000.00' 
      ,text: 'Superficie' 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'residents' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0,000,000' 
      ,text: 'residenti' 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'icon' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'string' } 
      ,flex: 1 
      ,text: 'Icona' 
      ,xtype: 'gridcolumn' 
     }] 
     ,columnLines: true 
     ,emptyText: '<font color="red"><b>Nessun comune in archivio</b></font>' 
     ,features: [ 
      Ext.create('GVD.ux.grid.FiltersFeature', { 
       encode: true, 
       ftype: 'filters', 
       local: false, 
       menuFilterText: 'Filtro' 
      }) 
     ]  
     ,id: 'municipalitiesGrid' 
     ,plugins: [ Ext.create('Ext.grid.plugin.RowEditing', { ptype: 'rowediting' }) ] 
     ,selModel: { selType: 'checkboxmodel', mode: 'MULTI' },store: 'Provinces' 
     ,store: 'Municipalities' 
     ,viewConfig: { 
      loadingText: 'Caricamento dati'  
      ,stripeRows: true 
      ,trackOver: true 
     } 
     ,xtype: 'grid' 
    }] 
    ,layout: { 
     align: 'stretch' 
     ,type: 'vbox' 
    } 
    ,margin: '0 0 2 0' 
    ,maximizable: true 
    ,minimizable: true 
    ,requires: [ 
     'GVD.ux.combo.Countries' 
     ,'GVD.ux.combo.Provinces' 
     ,'GVD.ux.combo.Regions' 
     ,'GVD.ux.PrintButton' 
     ,'GVD.ux.toolbar.BottomBar' 
     ,'GVD.ux.toolbar.PagingToolBar' 
     ,'GVD.ux.toolbar.TopBar' 
    ] 
    ,singleWindow: true 
    ,title: 'Elenco comuni' 
    ,tools: [ 
     { xtype: 'printButton', title: 'Elenco Comuni', tooltip: 'Stampa elenco' } 
     ,{ type: 'help', xtype: 'tool', tooltip: 'Guida sulla funzione' } 
    ] 
    ,width: 760 
}); 

希望這可以幫助。

bye

+0

我很欣賞這個答覆和答案,但我已經開始了,並且很高興與qooxdoo在一起,希望這可以幫助別人! – dan 2013-08-21 17:51:46