Knockoutjs:如何使添加到列表中的输入值也可观察
Posted
技术标签:
【中文标题】Knockoutjs:如何使添加到列表中的输入值也可观察【英文标题】:Knockoutjs: how can I make the input value added to a list also observable 【发布时间】:2019-08-02 22:22:58 【问题描述】:不确定我的措辞是否正确。
我有一个 observableArray,我可以从输入添加到该数组,还可以删除列表项。但是如果我修改创建的项目,我将失去与数组的连接。如何保持与数组的绑定?
Fiddle Attached
<div class="group-settings-container mt-4">
<div class="row">
<div class="col-md-3">
<h4><i class="fas fa-object-group"></i> Create Groups</h4>
</div>
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control create-group-name" data-bind="value: groupItemToAdd, valueUpdate: 'afterkeydown' " placeholder="Enter group name" value="">
<div class="input-group-append">
<button class="btn btn-primary add-group-btn" data-bind="click: addGroupItem, enable: groupItemToAdd().length > 0" type="button"><i class="fas fa-plus"></i>
Add group</button>
</div>
</div>
</div>
<div class="create-groups-container mb-4">
<ul class="list-group create-group-list my-2" data-bind="foreach: allGroupItems">
<li class="list-group-item">
<div class="input-group">
<input type="text" class="form-control created-group-input" data-bind="value: $data">
<div>
<button class="btn btn-danger remove-group-item-btn" data-bind="click: $parent.removeSelectedGroupItem" type="button"><i class="fas fa-times"></i>
Remove</button>
</div>
</div>
</li>
</ul>
</div>
<!-- end create groups container -->
</div>
<!-- end group settings container -->
JS
function ViewModel()
var self = this;
self.groupItemToAdd = ko.observable("");
self.allGroupItems = ko.observableArray([]);
self.addGroupItem = function()
if ((self.groupItemToAdd() != "") && (self.allGroupItems.indexOf(self.groupItemToAdd()) < 0))
self.allGroupItems.push(self.groupItemToAdd());
self.groupItemToAdd(""); // clear the input
self.removeSelectedGroupItem = function(index)
// self.allGroupItems.splice(index, 1);
// console.log(self.allGroupItems.splice(index, 1));
self.allGroupItems.remove(index);
// end ViewModel
ko.applyBindings(new ViewModel());
【问题讨论】:
如果答案解决了您的问题,请将其标记为accepted。见:What should I do when someone answers my question? 【参考方案1】:您有一个observableArray
。这意味着,对阵列的任何更改都会被跟踪和更新。它里面的项目只是字符串。他们不是observables
。您从 UI 所做的任何更改都不会更新回视图模型。此行为不限于字符串。如果你有一个 observableArray
的常规 javascript 对象文字,同样的事情也适用。
来自documentation:
仅仅将一个对象放入
observableArray
并不会使该对象的所有属性都成为observable
。当然,如果您愿意,您可以使这些属性可观察,但这是一个独立的选择。observableArray
只跟踪它持有的对象,并在添加或删除对象时通知侦听器。
因此,您可以将具有observable
属性的对象推送到observableArray
,而不是向observableArray
添加字符串。现在跟踪item
属性的更改。将属性设为observable
很重要,否则您会遇到同样的问题。
function ViewModel()
var self = this;
self.groupItemToAdd = ko.observable("");
self.allGroupItems = ko.observableArray([]);
self.addGroupItem = function()
if (self.groupItemToAdd() && !self.allGroupItems().some(a => a.item() === self.groupItemToAdd()))
self.allGroupItems.push(
item: ko.observable(self.groupItemToAdd())
);
self.groupItemToAdd(""); // clear the input
self.removeSelectedGroupItem = function(index)
self.allGroupItems.remove(index);
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<div class="group-settings-container mt-4">
<div class="row">
<div class="col-md-3">
<h4><i class="fas fa-object-group"></i> Create Groups</h4>
</div>
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" data-bind="value: groupItemToAdd, valueUpdate: 'afterkeydown' " placeholder="Enter group name">
<div class="input-group-append">
<button class="btn btn-primary add-group-btn" data-bind="click: addGroupItem, enable: groupItemToAdd().length > 0" type="button">Add group</button>
</div>
</div>
</div>
<ul class="list-group create-group-list my-2" data-bind="foreach: allGroupItems">
<li class="list-group-item">
<div class="input-group">
<input type="text" class="form-control created-group-input" data-bind="value: item">
<div>
<button class="btn btn-danger remove-group-item-btn" data-bind="click: $parent.removeSelectedGroupItem" type="button">Remove</button>
</div>
</div>
</li>
</ul>
</div>
<span data-bind="text: allGroupItems().map(a => a.item())"></span>
注意:
您需要将foreach
中的输入绑定从$data
更改为item
(可观察的属性名称)
要检查是否已添加组项目,请使用some
,如下所示:self.allGroupItems().some(a => a.item() === self.groupItemToAdd())
最后一个 span
表明 observable 已更新
【讨论】:
以上是关于Knockoutjs:如何使添加到列表中的输入值也可观察的主要内容,如果未能解决你的问题,请参考以下文章