【问题标题】:dynamic column and rows with knockoutjs带有knockoutjs的动态列和行
【发布时间】:2013-04-26 21:42:00
【问题描述】:

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

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

【问题讨论】:

  • 所以对~/api/inventories/ 的调用只能获取列名?调用~/api/ 的结果数据如何?
  • Tomalak,这是结构 '[{"$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} ]'
  • 嗯,这就是您问题中的数据结构。我想看看 other 数据结构。特别是我想看看当有多行时它的样子。

标签: knockout.js knockout-mvc


【解决方案1】:

重写了我的 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 正确的方向。我有一些改进的想法,但我需要查看两个 Ajax 调用的结果。
  • 我很高兴学习。 self.item(data) = //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":"双向"}]
  • self.tbstruct = //预期数据 //[{"$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} ]
  • 看看这个:jsfiddle.net/Tomalak/A6T8p。我也在写一个带有一些解释的新答案。
【解决方案2】:
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 将替换整个可观察对象,从而导致页面受影响部分的完全重建。指定 key 允许部分页面更新,因此在此处使用数据的唯一属性。 (如果您不打算在页面生命周期内从服务器刷新数据,则此步骤可能没有必要。)
  • ko.utils.unwrapObservable() 的使用是强制性的,因为在加载操作期间,key 将用于现有的视图模型内容服务器响应,例如,data.ColumnName 可能是可观察或原始值。
  • 请务必通读mapping plugin documentation 的高级部分,您可能会发现其他有用的信息。

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 的唯一地方是&lt;tr data-bind="foreach: $root.columns"&gt; 绑定。其他只是为了保持一致性。
  • $parent 指的是来自foreach: $root.rows 的行。
  • $parent[ColumnName()] 中的括号是必需的,因为ColumnName 是可观察的,并且在复杂的绑定中它们不会自动解包。

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

【讨论】:

  • 好多了。谢谢!
  • 哇,这好多了。谢谢!我正在从这个表中创建创建更新删除访问。 (动态)我需要做一些列过滤,我以前的方法是function ColName(tbstruct){ this.HeaderName =tbstruct.ColumnName.replace('_',' ') this.ColumnName = tbstruct.ColumnName, this.PrimaryKey = tbstruct.PrimaryKey, this.SystemField = tbstruct.ColumnName.indexOf('SYS'), this.Visible = tbstruct.ColumnName.indexOf('SYS'), this.HrefDetailsPage = function(item) { alert(invtype + '/' + item.Id); }; }
  • 上述函数实际上将系统字段名称重构为用户友好的输出。
  • 重建 var columnDefs 中的字段对我来说是否明智?
  • @SiGaban 我将使用自定义子视图模型和create 映射。您可能会从中得到一些想法:jsfiddle.net/Tomalak/A6T8p/1
猜你喜欢
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 2014-04-26
相关资源
最近更新 更多