淘汰赛:“更新为文本”框值未更新可观察项

时间:2018-09-05 02:11:56

标签: javascript html data-binding knockout.js two-way-binding

我有一个ObservavleArray,在加载UI时会使用两项进行初始化。

现在有一个添加按钮,可将新的可观察项推入可观察数组。效果很好。

但是当我在文本框中编辑值并且希望它们在基础可观察项上发生更改时,但这不会发生。

这是该代码段。

 var InventoryViewModel = function() {
     var self = this;
     self.STockItems = ko.observableArray();

     InitializeStock(self);

     self.addItems = function(vm) {
         self.STockItems.push(new ko.observable(''));
     }
     self.ProcessInventory = function(vm) {
         console.log(vm.STockItems());
     };
 }

 var vm = new InventoryViewModel();
 ko.applyBindings(vm);


 function InitializeStock(context) {
     context.STockItems.push(new ko.observable('Item1'));
     context.STockItems.push(new ko.observable('Item2'));
 }
li {
    list-style: none;
    margin-top: 10px;
}

.info-text {
    margin-top: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<ul data-bind="foreach: STockItems">
    <li>
        <span class="input-group">
            <input  data-bind="textInput: $data" />                                       
        </span>

    </li>
</ul>
<div class="text-right"> <a data-bind="click:addItems">+ Add more</a></div>
<button type="submit" class="btn btn-accent" data-bind="click: $root.ProcessInventory">Process Inventory</button>
<pre class='info-text' data-bind="text: ko.toJSON($data, null, '\t')">
</pre>

http://jsfiddle.net/xvza6nu2/1/

编辑: 当我直接推送可观察的项目时,我想我不必创建包装程序来推送项目。

function EditableField(initialValue) {
  this.value = ko.observable(initialValue);
}

如果必须使用此包装器,为什么?有什么区别?

1 个答案:

答案 0 :(得分:1)

可观察对象需要绑定到视图模型中的属性,这是从HTML引用它们的唯一方法。 $ data是对视图模型上下文的引用,而不是可观察对象本身。碰巧的是,在您的foreach上下文中,只有1个可观察到的,因此您的初始设置似乎可以正常工作。

阅读有关绑定上下文here的所有信息。

要使其正常工作,您需要将对象放入具有指定属性的observableArray中,该属性稍后将从HTML进行引用。 observableArray中的每个对象在foreach循环中成为一个微型视图模型。

修改

  1. 无需使用new来创建可观察的对象。
  2. $root引用主viewModel。当我们想从孩子的/后代的viewModel引用它时,使用它很有用。对于您来说,ProcessInventory单击是不需要的,因为我们已经在主要的viewModel上下文中。

 var InventoryViewModel = function() {
     var self = this;
     self.STockItems = ko.observableArray();

     InitializeStock(self);

     self.addItems = function(vm) {
         self.STockItems.push({item : ko.observable('')});
     }
     self.ProcessInventory = function(vm) {
         console.log(vm.STockItems());
     };
 }

 var vm = new InventoryViewModel();
 ko.applyBindings(vm);


 function InitializeStock(context) {
     context.STockItems.push({item : ko.observable('Item1')});
     context.STockItems.push({item : ko.observable('Item2')});
 }
li {
    list-style: none;
    margin-top: 10px;
}

.info-text {
    margin-top: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<ul data-bind="foreach: STockItems">
    <li>
        <span class="input-group">
            <input  data-bind="textInput: item" />                                       
        </span>

    </li>
</ul>
<div class="text-right"> <a data-bind="click:addItems">+ Add more</a></div>
<button type="submit" class="btn btn-accent" data-bind="click: ProcessInventory">Process Inventory</button>
<pre class='info-text' data-bind="text: ko.toJSON($data, null, '\t')">
</pre>