两种方式的数据绑定不适用于剔除ObservableArrays

时间:2018-08-30 10:57:53

标签: javascript html mvvm data-binding knockout.js

我有以下代码,它具有两个功能。

  1. 点击“添加更多”,将新值推送到可观察数组,将新文本框添加到UI
  2. 单击“保存”时,在div文本框中显示值。

var model = function() {
  var self = this;
  self.inventoryItems = ko.observableArray();

  myArray = ["Value1", "V1lue2", "Value3", "Value4"];
  self.inventoryItems(myArray);

  self.addItems = function(vm) {
    self.inventoryItems.push('New Item');
  }

  self.SaveInventory = function(data) {
    $('#htmlBlock').html(myArray);
    console.log(myArray)
  };

};

ko.applyBindings(new model());
ul {
  list-style: none;
}

li {
  margin-top: 5px;
}

.info-text,
a,
button {
  margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: inventoryItems">
  <li>
    <input data-bind="value: $data" />
  </li>
</ul>
<div>
  <a data-bind="click: addItems">+ Add more</a>
</div>
<button type="submit" class="btn btn-accent" data-bind="click: SaveInventory">Save changes</button>
<div class='info-text' id="htmlBlock">
</div>

使用此代码,我的UI可以很好地初始化,当我单击“添加更多”时,能够获得新的文本框,并且myArray / inventoryItems也可以正常工作。

但是,如果我编辑任何项目并保存该值,则不会获得更新值。

我想念什么?

1 个答案:

答案 0 :(得分:2)

在可观察数组中不需要对底层数组的单独引用,它只会使事情变得混乱。通过使用self.inventoryItems()读出值。

一种实时查看模型外观的好方法是使用带有data-bind="text: ko.toJSON($data, null, '\t')"的元素

要进行双向绑定,您需要使每个值(对于输入字段)都是可观察的。通常我会为此使用一个单独的构造函数。

function EditableField(initialValue) {
  // each value you want to be able to have a two-way binding for needs to be observable
  this.value = ko.observable(initialValue);
}

var model = function() {
  var self = this;
  self.inventoryItems = ko.observableArray(["Value1", "V1lue2", "Value3", "Value4"].map(function(item) {
    // run each array value through constructor
    return new EditableField(item);
  }));

  self.addItems = function(vm) {
    self.inventoryItems.push(new EditableField('New Item'));
  }

  self.SaveInventory = function(data) {
    console.log(ko.toJS(self.inventoryItems)); // fetch the updated array
  };

};

ko.applyBindings(new model());
ul {
  list-style: none;
}
li {
  margin-top: 5px;
}
.info-text,
a,
button {
  margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: inventoryItems">
  <li>
    <!-- use textInput binding for live updates, bound to the value property from constructor -->
    <input data-bind="textInput: value" />
  </li>
</ul>
<div>
  <a data-bind="click: addItems">+ Add more</a>
</div>
<button type="submit" class="btn btn-accent" data-bind="click: SaveInventory">Save changes</button>

<!-- display the model in real time -->
<pre class='info-text' data-bind="text: ko.toJSON($data, null, '\t')">
</pre>