2014年2月24日 星期一

ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 動態複製表單並送出

在看到這篇教學,請先參考 ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 送出表單 ( Submit Form )

上一篇教學是教大家如何將產品表單做出來並且送到 Controller 內對資料庫做新增的動作,接下來就來教大家如何做動態複製表單並且送出。

要寫好 Controller 要如何接收:
public HttpResponseMessage Post(IEnumerable<Products> products)
{
    if (ModelState.IsValid)
    {
        foreach(Products _product in products)
            db.Products.Add(_product);
        db.SaveChanges();

        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, products);
        // response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = products.ProductID }));
        return response;
    }
    else
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }
}


送到 Controller 必須要注意每一個欄位的 name 都必須是陣列型態的,例如:[0].ProductName、[1].UnitPrice、...等,所以在將表單複製出來後,每個欄位的 name 屬性必須重新命名,這樣一來,Controller 才能接收到正確資訊。

先將表單內容物件宣告出來:
var container = {
    id: 'container',
    height: 250,
    xtype: 'container',
    border: 1,
    padding: '10 10 10 10',
    style: { borderColor: '#000000', borderStyle: 'solid', borderWidth: '1px' },
    defaultType: 'textfield',
    items: [
        {
            itemId: 'ProductNameId',
            name: 'ProductName',
            fieldLabel: '產品名稱',
            maxLength: 50,
            maxLengthText: '最大長度為 50 字元',
            allowBlank: false
        },
        {
            itemId: 'CategoryId',
            name: 'CategoryID',
            fieldLabel: '產品類別',
            xtype: 'combo',
            valueField: 'CategoryID',
            displayField: 'CategoryName',
            queryMode: 'local',
            store: storeCategories,
            emptyText: '請選擇產品類別',
            allowBlank: false
        },
        {
            itemId: 'SupplierId',
            name: 'SupplierID',
            fieldLabel: '貨運公司',
            xtype: 'combo',
            valueField: 'SupplierID',
            displayField: 'CompanyName',
            queryMode: 'local',
            store: storeSuppliers,
            emptyText: '請選擇貨運公司',
            allowBlank: false
        },
        {
            itemId: 'QuantityPerUnitId',
            name: 'QuantityPerUnit',
            fieldLabel: '單位數量',
            maxLength: 50,
            maxLengthText: '最大長度為 50 字元',
            allowBlank: true
        },
        {
            itemId: 'UnitPriceId',
            name: 'UnitPrice',
            fieldLabel: '單價',
            allowBlank: false,
            regex: /^[\$]?[\d]*(.[\d]+)?$/,
            regexText: '金額格式錯誤',
            maskRe: /[\d\$.]/,
        },
        {
            itemId: 'UnitsInStockId',
            name: 'UnitsInStock',
            fieldLabel: '單位庫存量',
            allowBlank: false,
            regex: /^[\d]*$/,
            regexText: '格式錯誤',
            maskRe: /[\d]/,
        },
        {
            itemId: 'UnitsOnOrderId',
            name: 'UnitsOnOrder',
            fieldLabel: '已訂購量',
            allowBlank: false,
            regex: /^[\d]*$/,
            regexText: '格式錯誤',
            maskRe: /[\d]/,
        },
        {
            itemId: 'DiscontinuedId',
            name: 'Discontinued',
            fieldLabel: '不再銷售',
            width: 400,
            xtype: 'radiogroup',
            vertical: false,
            allowBlank: false,
            items: [
                {
                    boxLabel: '是',
                    name: 'discontinued',
                    inputValue: 'true'
                }, {
                    boxLabel: '否',
                    name: 'discontinued',
                    inputValue: 'false'
                }
            ]
        },
    ]
}

而實際上在顯示的表單內的 items 是沒有內容的,如果要預設一筆,就將上面的表單欄位加上去就好了:
var form = Ext.create('Ext.form.Panel', {
    renderTo: Ext.getBody(),
    collapseFirst: false,
    title: '新增產品資料',
    id: 'form',
    bodyPadding: '5 5 5 5',
    width: 500,
    fieldDefaults: {
        msgTarget: 'side',
        labelWidth: 120
    },
    defaults: {
        margin: '0 0 5 0',
    },
    plugins: {
        ptype: 'datatip'
    },
    defaultType: 'textfield',
    items: [
        
    ],
    tools: [
       {
           type: 'save',
           callback: function () {
               // show help here
               if (this.up('form').getForm().isValid()) {
                   $.ajax({
                       url: 'http://localhost:8090/api/Product/Post',
                       data: this.up('form').getForm().getValues(),
                       type: 'POST',
                       error: function () { alert('Error!!'); },
                       success: function () {
                           alert('Success!!');
                       }
                   });
               }
               console.log(this.up('form').getForm().getValues())
           }
       },
       {
           type: 'plus',
           callback: function () {
               // show help here
               newContainer();

           }
       }
    ],
});


利用 jQuery.extend 將表單複製出來,要另外寫 function 做這件事情,在 function 必須要做到複製以及將 name 更名,比較要注意的是,:
var counterNew = 0; 
function newContainer() {
    var tContainer = jQuery.extend(true, {}, container);
    var tHeader = '[' + counterNew + '].';
    tContainer.id = tContainer.id + counterNew;
    for (var i = 0; i < tContainer.items.length; i++) {
        
        console.log(tContainer.items[i].xtype);

        if (tContainer.items[i].xtype == 'radiogroup')
        {
            for (var j = 0 ; j < tContainer.items[i].items.length; j++) {
                tContainer.items[i].items[j].name = tHeader + tContainer.items[i].items[j].name;
            }
        }
        else {
            tContainer.items[i].name = tHeader + tContainer.items[i].name;
        }
    }
    Ext.getCmp('form').add(tContainer);
    counterNew++;
}

最後要在實際表單上加上 tools,按下時呼叫此 function:
{
    type: 'plus',
    callback: function () {
        // show help here
        newContainer();
    }
}

頁面上就會顯示:

執行後按下新增按鈕,如果不打上任何資料,會如同以下圖:

打上資料後送出:

程式中設定中斷點,就會看到資料皆有被傳遞:

最後資料庫就會新增此筆資料:


沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...