兩個或更多的下拉式選項要做資料連動,前提就是要在這兩份資料必須要有關聯,不管是一對多還是多對一。
以往在做 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'
}]
});
});