动态列和具有knockoutjs的行

时间:2013-05-02 16:07:54

标签: knockout.js knockout-mvc

下面代码的输入参数只是一个表名,

我能够以json格式查询数据返回,  但是,我无法显示我的行数据项。  知道我做错了什么吗?

<script>
var invtype = "@ViewBag.invtype";

    function ViewModel() {  

        var self = this;
        function ColName(tbstruct){ 
            this.ColumnName = tbstruct.ColumnName
        }

        self.TBStruct = ko.observableArray(); 
        self.items = ko.observableArray(); 

        self.invtype = invtype;

        self.Load = function () {


    //expected data for self.items
    //[{"$id":"1","Id":2,"Inv_Id":"PV0001-1","ACX_No":"6","ACX_Name":"ABC","S_No":"5", "Acc_Class":"Local","Direction":"Two-Way"},{"$id":"2","Id":2,"Inv_Id":"PV0002-1","ACX_No":"3","ACX_Name":"CKD","S_No":"6", "Acc_Class":"Local","Direction":"Two-Way"}]


            $.ajax({
                    url: "@Url.Content("~/api/")"+self.invtype, 
                    type: 'GET',
                    dataType: 'JSON',
                    success: function (data) {
                        // Map the returned JSON to the View Model  

                        self.items = data;
                    }
            });

//expected data
     //[{"$id":"1","ColumnName":"Id","system_type_id":56,"primaryCol":1}, {"$id":"2","ColumnName":"Inv_Id","system_type_id":231,"primaryCol":0},{"$id":"3","ColumnName":"ACX_No","system_type_id":175,"primaryCol":0},{"$id":"4","ColumnName":"ACX_Name","system_type_id":175,"primaryCol":0},{"$id":"5","ColumnName":"S_No","system_type_id":175,"primaryCol":0} {"$id":"27","ColumnName":"Acc_Class","system_type_id":231,"primaryCol":0},{"$id":"28","ColumnName":"Direction","system_type_id":231,"primaryCol":0} ]

            $.ajax({
                    url: "@Url.Content("~/api/inventories/")"+self.invtype,
                    type: 'GET',
                    dataType: 'JSON',
                    success: function (data) {
                        // Map the returned JSON to the View Model  
                        $.each(data,function(i,dt){
                            //console.log(dt.ColumnName);
                            self.TBStruct.push(new ColName(dt));
                        });
                        //console.dir(self.TBStruct);
                    }
            });
            return self;
        };
    } 

    var View = new ViewModel();
    ko.applyBindings(View.Load()); 

这里我试图展示它们。

    <thead>
        <tr data-bind="foreach: TBStruct">
            <th data-bind="text: ColumnName"></th>
        </tr>
    </thead>

    <tbody >
        <tr data-bind="foreach: items" >
            <td data-bind="text:$data"></td> 
        </tr> 
    </tbody>
</table>

2 个答案:

答案 0 :(得分:3)

重写了我的self.load

         self.Load = function () {
            $.ajax({
                url: "@Url.Content("~/api/")"+self.invtype, 
                type: 'GET',
                dataType: 'JSON',
                success: function (data) {
                    // Map the returned JSON to the View Model  
                    ko.mapping.fromJS(data,{}, self.items);   
                }
            });
            $.ajax({
                url: "@Url.Content("~/api/inventories/")"+self.invtype,
                type: 'GET',
                dataType: 'JSON',
                success: function (data) {
                    // Map the returned JSON to the View Model  
                    $.each(data,function(i,dt){ 
                        self.TBStruct.push(new ColName(dt));
                    }); 
                }
            });
            return self;
        };

输出迭代

        <thead>
        <tr data-bind="foreach: TBStruct">
        <th data-bind="text: HeaderName,visible: SystemField == -1 || Visible" ></th>
        </tr>
        </thead>
        <tbody data-bind="foreach: items " >
        <tr data-bind="foreach: $root.TBStruct, click:function() { alert('me');}" id="rowData">
         <td data-bind="text: $parent[ColumnName],visible: SystemField == -1 || Visible" ">
         </td> 
         </tr> 
            </tbody>

答案 1 :(得分:3)

function ViewModel() {
    var self = this;

    self.invtype = "@ViewBag.invtype";
    self.columns = ko.observableArray();
    self.rows = ko.observableArray();

    self.load = function () {
        $.when(
            $.get("@Url.Content('~/api/inventories/')" + self.invtype),
            $.get("@Url.Content('~/api/')" + self.invtype)
        )
        .then(function (columnResponse, rowResponse) {
            var columnDefs = columnResponse[0],
                rowDefs = rowResponse[0],
                columnMapping = {
                    key: function (data) {
                        return ko.utils.unwrapObservable(data.ColumnName);
                    }
                },
                rowMapping = {
                    key: function (data) {
                        return ko.utils.unwrapObservable(data.Id);
                    }
                };

            ko.mapping.fromJS(columnDefs, columnMapping, self.columns);
            ko.mapping.fromJS(rowDefs, rowMapping, self.rows);
        });

        return self;
    };
}

注意:

  • 使用jQuery的.when().then()可确保只有在两个HTML请求都成功返回后才会进行视图模型处理。见jQuery's documentation on the topic
  • 自定义映射中的key函数可确保在再次调用load()时,只有视图模型的相应部分才会获得更新。否则ko.mapping.fromJS将替换整个observable,从而完全重新构建页面的受影响部分。指定key允许部分页面更新,因此请在此处使用数据的唯一属性。 (如果您不打算在页面生命周期内从服务器刷新数据,则可能不需要执行此步骤。)
  • 使用ko.utils.unwrapObservable()是必需的,因为在加载操作期间key将在现有的视图模型内容上使用服务器响应,例如{{} 1}}可以是可观察的或原始值。
  • 请务必阅读mapping plugin documentation的高级部分,您可能会发现其他有用的内容。

HTML

data.ColumnName

注意:

  • 实际需要<table> <thead> <tr data-bind="foreach: $root.columns"> <th data-bind="text: ColumnName"></th> </tr> </thead> <tbody data-bind="foreach: $root.rows"> <tr data-bind="foreach: $root.columns"> <td data-bind="text: $parent[ColumnName()]"></td> </tr> </tbody> </table> 的唯一地方是$root绑定。其他仅包括在内以保持一致性。
  • <tr data-bind="foreach: $root.columns">指的是$parent
  • 中的行
  • foreach: $root.rows中的括号是必要的,因为$parent[ColumnName()]是一个可观察的,并且在复杂的绑定中,它们不会自动解包。

这里可以看到整个事情:http://jsfiddle.net/Tomalak/A6T8p/
和这里(扩展版):http://jsfiddle.net/Tomalak/A6T8p/1