-->

动态列和行与knockoutjs(dynamic column and rows with knoc

2019-09-01 18:59发布

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

我能够查询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>

Answer 1:

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的的话题文档 。
  • key自定义映射功能可以确保当你调用load()又那么只有您的视图模型的相应部分得到更新。 否则ko.mapping.fromJS将替换整个观察到的,导致你的页面的患部完全重新构建。 指定key允许部分页面更新,所以在这里用你的数据的唯一财产。 (如果你没有在在网页的续航时间从服务器刷新数据计划这一步可能没有必要。)
  • 使用ko.utils.unwrapObservable()是强制性的,因为在加载操作key将在现有的视图模型内容服务器响应都使用,所以例如data.ColumnName可以是可观察到的或原始值。
  • 一定要通过的先进部分,阅读地图插件文档 ,你可能会发现其他有用位。

HTML

<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()]是必要的,因为ColumnName是可观察到的,并在复合物结合它们不会自动解开。

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



Answer 2:

重写我的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>


文章来源: dynamic column and rows with knockoutjs