2014年1月29日 星期三

ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 列表 ( List )

在看到這篇教學,請先參考 Visual Studio 2012 安裝 Northwind 資料庫並建立 Entity Framework Database First ( .edmx ) 以及 ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 基本配置

使用 Extjs 建立 List 表格,在 WebForm 的情況下,利用 GridView 和 ADO.NET 就可以很迅速地建立表格,如果再套用 bootstrap,那就很舒服了。

但是當你表格要自己設計,連資料庫給的資料 ( json 格式 ) 都必須要對好欄位自己擺放,假設今天一個 List 已經很辛苦的寫好了,但是隔天老闆或客戶又要改欄位位置,那一定會叫苦連天,這時,Extjs 強大功能就會體現出來了,只需要變動幾行程式碼就可以達到欄位調換的功能,甚至可以拖曳欄位給使用者更友善的介面。

1.

首先必須要先建立資料來源的模型 ( Model ),名稱定義為 'Model',以下程式碼是以 Employee 表產生的欄位:
// 定義 data model 定義資料欄位 欄位型態
Ext.define('Model', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'EmployeeID', type: 'string' },
        { name: 'LastName', type: 'string' },
        { name: 'FirstName', type: 'string' },
        { name: 'Title', type: 'string' },
        { name: 'TitleOfCourtesy', type: 'string' },
        { name: 'BirthDate', type: 'date' },
        { name: 'HireDate', type: 'date' },
        { name: 'Address', type: 'string' },
        { name: 'City', type: 'string' },
        { name: 'Region', type: 'string' },
        { name: 'PostalCode', type: 'string' },
        { name: 'HomePhone', type: 'string' },
        { name: 'Extension', type: 'int' },
        { name: 'Notes', type: 'string'},
        { name: 'ReportsTo', type: 'string' },
        { name: 'PhotoPath', type: 'string' },
        { name: 'Country', type: 'string' },
        { name: 'Photo', type: 'auto', },
        { name: 'mappingField', type: 'auto', mapping: 'EmployeeID' }
        // mapping 到 EmployeeID 即值 = EmployeeID  [mapping Ex. mapping Name.FirstName 即取 Name 這個類別裡 First Name 的值]

    ],
})

2.

接著讀取 API 的資料將資料解析成 'Model' 的格式,建立 Ext.data.JsonStore 塞到變數 store。

var store = Ext.create('Ext.data.JsonStore', {
    storeId: 'store',
    model: 'Model', // 指定data model
    //fields: ['EmployeeID', 'LastName', 'FirstName', 'Title', 'TitleOfCourtesy', 'BirthDate', 'HireDate', 'Address', 'City', 'Region', 'PostalCode', 'Country', 'HomePhone', 'Extension', 'Notes', 'ReportsTo', 'PhotoPath', 'Photo'],
    proxy: {
        type: 'ajax',
        url: 'http://localhost:8090/api/Employee',
        reader: {
            type: 'json',
        }
    },
    autoLoad: true, // 自動載入
    listeners: {
        load: function (store, records, options) {
        }
    },

});

3.

設定欄位過濾器 ( 視所需 ),是針對欄位做字串搜尋的功能,若是日期格式就是日期期間搜尋。

日期篩選:

字串篩選:

// 欄位過濾器
var filters = { 
    ftype: 'filters',
    encode: false, 
    local: true, 
    filters: [{
        type: 'boolean',
        dataIndex: 'visible'
    }]
};

4.

設定 toolbar ( 視所需 ),如果有需要整批修改或整批刪除,這裡可以加入。


//建立toolbar
dockedItems: [Ext.create('Ext.toolbar.Toolbar', { 
    dock: 'top', // 置頂
    items: [
        '->', // 靠右
        {   
            //建立button
            xtype: 'button', 
            text: 'toolbarButton',
            handler: function () {
                // 按下後動作
            }
        },
        {
            xtype: 'button',
            text: 'toolbarButton2',
            handler: function () {
                // 按下後動作
            }
        }
    ]
})]

5.

設定讀取不到資料要顯示甚麼文字。


emptyText: 'No Matching Records'

6.

最後,完整程式碼為:

Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux', '/Scripts/ext/examples/ux');

Ext.require([
    'Ext.grid.*',
    'Ext.data.*',
    'Ext.panel.*',
    'Ext.layout.container.Border',
    'Ext.tab.*',
    'Ext.window.*',
    'Ext.tip.*',
    'Ext.ux.grid.FiltersFeature',
]);

Ext.onReady(function () {

    Ext.QuickTips.init(); //加這行 tip 才會顯示

    Ext.define('Model', {
        extend: 'Ext.data.Model',
        fields: [
            { name: 'EmployeeID', type: 'string' },
            { name: 'LastName', type: 'string' },
            { name: 'FirstName', type: 'string' },
            { name: 'Title', type: 'string' },
            { name: 'TitleOfCourtesy', type: 'string' },
            { name: 'BirthDate', type: 'date' },
            { name: 'HireDate', type: 'date' },
            { name: 'Address', type: 'string' },
            { name: 'City', type: 'string' },
            { name: 'Region', type: 'string' },
            { name: 'PostalCode', type: 'string' },
            { name: 'HomePhone', type: 'string' },
            { name: 'Extension', type: 'int' },
            { name: 'Notes', type: 'string'},
            { name: 'ReportsTo', type: 'string' },
            { name: 'PhotoPath', type: 'string' },
            { name: 'Country', type: 'string' },
            { name: 'Photo', type: 'auto', },
            { name: 'mappingField', type: 'auto', mapping: 'EmployeeID' },

        ],
    })


    var store = Ext.create('Ext.data.JsonStore', {
        storeId: 'store',
        model: 'Model',
        //fields: ['EmployeeID', 'LastName', 'FirstName', 'Title', 'TitleOfCourtesy', 'BirthDate', 'HireDate', 'Address', 'City', 'Region', 'PostalCode', 'Country', 'HomePhone', 'Extension', 'Notes', 'ReportsTo', 'PhotoPath', 'Photo'],
        proxy: {
            type: 'ajax',
            url: 'http://localhost:8090/api/Control',
            reader: {
                type: 'json',
            }
        },
        autoLoad: true,
        listeners: {
            load: function (store, records, options) {
            }
        },

    });

    var filters = { //
        ftype: 'filters',
        encode: false,
        local: true,

        filters: [{
            type: 'boolean',
            dataIndex: 'visible'
        }]
    };

    var gridPanel = Ext.create('Ext.grid.Panel', {
        renderTo: Ext.getBody(),
        store: store,
        itemId: 'gridPanel',
        region: 'north',
        //height: 460,
        split: true,
        collapsible: true,
        features: [filters],
        columns: [
                //flex  有width 寬為其值  剩下的撈會依比例 分剩下的欄寬  Ex. 5個欄位 flex 分別為  1 2 3 4 5   flex 為2 的就是  2/15 剩下的欄寬
                { text: 'EmployeeID', width: 100, dataIndex: 'EmployeeID', sortable: true, filter: true }, //filter 可篩選
                { text: 'LastName', flex: 1, dataIndex: 'LastName', sortable: true },
                { text: 'FirstName', flex: 1, dataIndex: 'FirstName', sortable: true },
                { text: 'Title', flex: 1, dataIndex: 'Title', sortable: true },
                { text: 'TitleOfCourtesy', flex: 1, dataIndex: 'TitleOfCourtesy', sortable: true, filter: true },
                { text: 'BirthDate', flex: 1, dataIndex: 'BirthDate', sortable: true, filter: true },
                { text: 'HireDate', flex: 1, dataIndex: 'HireDate', sortable: true, filter: true, renderer: Ext.util.Format.dateRenderer('Y/m/d A g:i:s '), },// formate 時間格式
                { text: 'Address', flex: 1, dataIndex: 'Address', sortable: true, filter: true },
                { text: 'City', flex: 1, dataIndex: 'City', sortable: true, filter: true },
                { text: 'Region', flex: 0.5, dataIndex: 'Region', sortable: true, filter: true },
                { text: 'PostalCode', flex: 1, dataIndex: 'PostalCode', sortable: true, filter: true },
                { text: 'Country', flex: 1, dataIndex: 'Country', sortable: true, filter: true,  },
                { text: 'HomePhone', flex: 1, dataIndex: 'HomePhone', sortable: true, filter: true },
                { text: 'Extension', flex: 1, dataIndex: 'Extension', sortable: true, filter: true },
                { text: 'mappingField', flex: 1, dataIndex: 'mappingField', sortable: true, filter: true }
        ],
        loadMask: true,
        dockedItems: [Ext.create('Ext.toolbar.Toolbar', {
            dock: 'top',
            items: [
                '->',
                {
                    xtype: 'button',
                    text: 'toolbarButton',
                    handler: function () {
                    }
                },
                {
                    xtype: 'button',
                    text: 'toolbarButton2',
                    handler: function () {
                    }
                }
            ]
        })],
        emptyText: 'No Matching Records',
    });
});

結果圖:


沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...