【问题标题】:table cell in view not updating when viewmodel is updated更新视图模型时视图中的表格单元格未更新
【发布时间】:2016-12-21 23:30:27
【问题描述】:

当我在 js/knockout 代码中更新视图模型时,我无法弄清楚为什么视图中的表格单元格没有更新。

这是我的fiddle,我在@haim770 和@Matt.kaaj 的帮助下工作。因此,当您从最后一行的最后一个单元格中跳出时。然后你在新行的第一个单元格中输入一些内容并使用标签,它应该会更新描述。我检查了控制台,它正在正确更新视图模型。谷歌搜索时,我发现我必须让我的可观察数组也包含可观察对象。所以我认为我使用映射插件正确地做到了这一点。 这是我所有的小提琴代码。

HTML:

<table class="table table-bordered table-striped" id="brochureItems">
<thead>
    <tr>
        <th>
            Item No.
        </th>
        <th>
            Broc Code
        </th>
        <th width="40%">
            Item Desc
        </th>
        <th>
            Retail
        </th>
        <th>
            Remove
        </th>
    </tr>
</thead>
<tbody data-bind="foreach: items">
    <tr>
        <td>
            <input data-bind="value: itemNo, hasFocus: true, event: { blur: $parent.checkItemNo }" class="form-control item-ID" />
        </td>
        <td>
            <div data-bind="if: ($index() < ($parent.items().length - 1))"><input data-bind="value: brocCode" class="form-control" readonly="readonly" /></div>
            <div data-bind="if: ($index() === ($parent.items().length - 1))"><input data-bind="value: brocCode" class="form-control" /></div>

        </td>
        <td class="item-desc">
            <input data-bind="value: itemDesc" class="form-control" tabindex="-1" />
        </td>
        <td class="item-retail">
            <div data-bind="if: ($index() === ($parent.items().length - 1))"><input data-bind="value: retail, valueUpdate: 'afterkeydown', enterPress: 'addRow'" class="form-control" /></div>
            <div data-bind="if: ($index() < ($parent.items().length - 1))"><input data-bind="value: retail, valueUpdate: 'afterkeydown'" class="form-control" /></div>
        </td>
        <td class="remove"><span class="glyphicon glyphicon-remove removeRow" data-bind="click: $parent.removeItem"></span></td>

    </tr>
</tbody>

JS/淘汰赛:

    var itemsModel = function(items) {
    var self = this;
  //console.log(JSON.stringify(items));
  //self.items = ko.observableArray();
  //ko.mapping.fromJS(items,{},self.items)
  //self.items = ko.mapping.fromJSON(items);
  //self.items = ko.observableArray(items);

  self.items = ko.mapping.fromJSON(items);

  self.checkItemNo = function(data) {
    console.log("blurred!");
    //data = ko.observable(data);
    //itemModel(data.itemNo)
    //var itemNo = $.trim(data.itemNo);
    var itemNo = "abc";
    if (itemNo != "") {
      var item = "";
        /*
        $.each(fullItemList, function(i, v) {
        if (v.No.search(itemNo) != -1) {
        item = v.Description;
        return;
        }
        });
        if(item != "") {
        console.log("found: " + item);
        var match = ko.utils.arrayFirst(self.items, function(item) {
        return itemNo === item.itemNo;
        });
        */
      var match = false;
      item = "Mudguard front";
      if (!match) {
        console.log("not a match!");
        console.log(data);
        data.itemDesc = item;
      }
    }
  }

  self.addLine = function() {
    self.items.push(
      {
        itemNo: "",
        brocCode: "",
        itemDesc: "",
        retail: ""
      }
    )
  };

  self.removeItem = function(item) {
    self.items.remove(item);
  };
};

ko.bindingHandlers.enterPress = {
  init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var allBindings = allBindingsAccessor();
    element.addEventListener('keydown', function (event) {
      var keyCode = (event.which ? event.which : event.keyCode);
      if (keyCode === 13 || (!event.shiftKey && keyCode === 9)) {
        event.preventDefault();
        console.log("hit enter/tab!");
        bindingContext.$root.addLine();
        return false;
      }
      return true;
    });
  }
};

function GetItems() {
            //var itemsJSON = @Html.Raw(Json.Encode(Model.brochureItems));
            var itemsJSON =  '[{"brochureId":1,"itemNo":"1000","brocCode":"1000","itemDesc":"Bicycle","retail":13.5},{"brochureId":1,"itemNo":"1100","brocCode":"1100","itemDesc":"Front Wheel","retail":35},{"brochureId":1,"itemNo":"1120","brocCode":"1120","itemDesc":"Spokes","retail":12.5},{"brochureId":1,"itemNo":"1150","brocCode":"1150","itemDesc":"Front Hub","retail":5},{"brochureId":1,"itemNo":"1151","brocCode":"1151","itemDesc":"Axle Front Wheel","retail":14},{"brochureId":1,"itemNo":"120","brocCode":"120","itemDesc":"Loudspeaker, Black, 120W","retail":12.5},{"brochureId":1,"itemNo":"125","brocCode":"125","itemDesc":"Socket Back","retail":10}]';
            var viewModel = new itemsModel(itemsJSON);
            ko.applyBindings(viewModel);
        }

$(document).ready(function () {
    GetItems();
});

更新

更新了代码,这里是新的fiddle

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    mapping plugin 为您完成这项工作,并为正在发送的数据创建可观察变量。添加新行后,您需要有一个子视图模型并添加该 VM 的新实例,该实例本身包含可观察变量。

    var itemsModel = function(items) {
        var self = this;
      //console.log(JSON.stringify(items));
      //self.items = ko.observableArray();
      //ko.mapping.fromJS(items,{},self.items)
      //self.items = ko.mapping.fromJSON(items);
      //self.items = ko.observableArray(items);
    
      self.items = ko.mapping.fromJSON(items);
    
      self.checkItemNo = function(data) {
        console.log("blurred!");
        //data = ko.observable(data);
        //itemModel(data.itemNo)
        //var itemNo = $.trim(data.itemNo);
        var itemNo = "abc";
        if (itemNo != "") {
          var item = "";
            /*
            $.each(fullItemList, function(i, v) {
            if (v.No.search(itemNo) != -1) {
            item = v.Description;
            return;
            }
            });
            if(item != "") {
            console.log("found: " + item);
            var match = ko.utils.arrayFirst(self.items, function(item) {
            return itemNo === item.itemNo;
            });
            */
          var match = false;
          item = "Mudguard front";
          if (!match) {
            console.log("not a match!");
            console.log(data);
            data.itemDesc = item;
          }
        }
      }
    
      self.addLine = function() {
        self.items.push(new RowViewModel() )
      };
    
      self.removeItem = function(item) {
        self.items.remove(item);
      };
    };
    
    var RowViewModel = function(){
      var self = this;
      self.itemNo = ko.observable();
      self.brocCode = ko.observable();
      self.itemDesc = ko.observable();
      self.retail = ko.observable();
    
    }
    

    【讨论】:

    • 谢谢。我添加了新的更改,但仍未按预期更新。 jsfiddle.net/rwa03vrb/7
    • 知道了!我没有正确设置 itemDesc。 data.itemDesc(item);