以往在做 WebForm 的時候,如果碰到要下拉選單連動的時候,都要在每次選項切換時,再去和資料庫撈一次資料,如果伺服器是自己的那倒無所謂,如果是使用雲端,使用多少算多少的計費方式,就不得不去計較小細節,因為這小細節很可能會變成大費用。
最理想的情況下,就是將連動的資料在 API 內就先做好,然後在頁面載入時,跟 API 要資料,也只要這麼一次,往後不管怎麼變動,都與資料庫無關。
所以現在就使用 Extjs 來實現 Combo 連動:
在此之前,若未建立資料庫和基本配置,請先參考 Visual Studio 2012 安裝 Northwind 資料庫並建立 Entity Framework Database First ( .edmx ) 以及 ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 基本配置
建立 Controller API
使用 Northwind 資料庫內產品類別和產品的一對多關聯的特性,來產生資料:public class CategoriesController : BaseApiController { public IEnumerable<Categories> Get() { var categories = db.Categories.Include(x => x.Products); foreach (Categories category in categories) { foreach (Products product in category.Products) product.Categories = null; } return db.Categories.AsEnumerable(); } protected override void Dispose(bool disposing) { db.Dispose(); base.Dispose(disposing); } }
資料格式為:
建立 Ext Model
必須要注意兩個屬性 hasMany 和 belongsTo,記得要對應好,hasMany 可以想成是這些資料要去連動哪個 Model,belongsTo 資料要依據哪一個 Model 來產生。來看程式碼就會知道了:Ext.define('Category', { extend: 'Ext.data.Model', fields: [ 'CategoryID', 'CategoryName' ], hasMany: { model: 'Product', name: 'Products' } }) Ext.define('Product', { extend: 'Ext.data.Model', fields: [ 'ProductID', 'ProductName' ], belongsTo: 'Category', })
接著將資料放到 Ext.data.JsonStore 物件內,請注意:產品資料內容不需要建立
var storeCategory = Ext.create('Ext.data.JsonStore', { storeId: 'storeCategory', model: 'Category', proxy: { type: 'ajax', url: 'http://localhost/api/Categories/', reader: { type: 'json', } }, // 自動載入 autoLoad: true, listeners: { // sotre load 完成後載入這個fucntion load: function (store, records, options) { } }, }) var storeProduct = Ext.create('Ext.data.JsonStore', { storeId: 'storeProduct', model: 'Product', })
建立欄位
這裡與上面的 Ext.data.JsonStore 有關聯,為什麼不建立產品資料內容?就是要等選擇後再建立。combobox 內有監看 ( listeners ) 事件,就等於 WebForm 的事件一樣,選擇後,先將產品下拉式選單清空,再將此資料下的 Product 資料放進去。
[ { xtype: 'combobox', fieldLabel: '類別', name: 'Category', //queryMode: 'local', store: storeCategory, editable:false, valueField: 'CategoryID', displayField: 'CategoryName', listeners: { select: function (combo, record, index) { // raw 取得選取的資料 var tempProducts = record[0].raw.Products; // 清空 product combobox 的store storeProduct.removeAll(); for (var i = 0; i < tempProducts.length; i++) { // 加到 product combobox 的store storeProduct.add(tempProducts[i]); } } } }, { xtype: 'combobox', fieldLabel: '產品', queryMode: 'local', name: 'Product', editable: false, store: storeProduct, valueField: 'ProductID', displayField: 'ProductName', } ]
最後結果就會如同以下畫面:
完整程式碼為:
// 載入會用到的程式 Ext.require([ 'Ext.form.*', 'Ext.layout.container.Absolute', 'Ext.window.Window', 'Ext.Button' ]); Ext.onReady(function () { Ext.define('Category', { extend: 'Ext.data.Model', fields: [ 'CategoryID', 'CategoryName' ], // Model Category 有 list Product hasMany: { model: 'Product', name: 'Products' } }) Ext.define('Product', { extend: 'Ext.data.Model', fields: [ 'ProductID', 'ProductName' ], belongsTo: 'Category', }) var storeCategory = Ext.create('Ext.data.JsonStore', { storeId: 'storeCategory', model: 'Category', proxy: { type: 'ajax', url: 'http://localhost:8090/api/Categories/', reader: { type: 'json', } }, // 自動載入 autoLoad: true, listeners: { // sotre load 完成後載入這個fucntion load: function (store, records, options) { } }, }) var storeProduct = Ext.create('Ext.data.JsonStore', { storeId: 'storeProduct', model: 'Product', }) //建立 form 框架 var form = Ext.create('Ext.form.Panel', { // 預設 tpe (xtype) 沒有指定就是textfield defaultType: 'textfield', // 不要外框 border: false, width: 300, // form 的形式顯示 items 自動填滿畫面 layout: 'form', // css padding 10 px padding: 10, renderTo: Ext.getBody(), items: [ { xtype: 'combobox', fieldLabel: '類別', name: 'Category', //queryMode: 'local', store: storeCategory, editable:false, valueField: 'CategoryID', displayField: 'CategoryName', listeners: { select: function (combo, record, index) { // raw 取得選取的資料 var tempProducts = record[0].raw.Products; // 清空 product combobox 的store storeProduct.removeAll(); for (var i = 0; i < tempProducts.length; i++) { // 加到 product combobox 的store storeProduct.add(tempProducts[i]); } } } }, { xtype: 'combobox', fieldLabel: '產品', queryMode: 'local', name: 'Product', editable: false, store: storeProduct, valueField: 'ProductID', displayField: 'ProductName', }, ], buttons: [{ text: 'Send', // button 按下動作 handler: function () { // 檢查form isValid 檢查條件是否符合 this.up('form').getForm().isValid(); // 取得from 所有欄位與值 name : value alert(JSON.stringify(this.up('form').getForm().getValues())) } }, { text: 'Cancel' }] }); });
沒有留言 :
張貼留言