我有一个具有设备名称和数量的json数组。如果数量为2,并且用户将两个项目添加到该名称的foreach(他们从下拉字段中选择),我想从下拉菜单中隐藏该设备名称选项。
*的 修改 * 符文似乎他有正确的答案,但我无法弄清楚如何将它集成到我的代码中。这是我的代码:http://jsfiddle.net/QTUqD/1/
<form id="extMngForm">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Extension</th>
<th>Name</th>
<th>Email</th>
<th>Voicemail Pin</th>
<th>Device</th>
<th>MAC Address</th>
<th>Ship To</th>
<th style="width: 100px; text-align:right;" />
</tr>
</thead>
<tbody data-bind=" template:{name:templateToUse, foreach: pagedList }"></tbody>
</table>
<!-- ko if: pagedList().length < extQty() -->
<p class="pull-right"><a class="btn btn-primary" data-bind="click: $root.add" href="#" title="edit"><i class="icon-plus"></i> Add Extension</a></p>
<!-- /ko -->
<div class="pagination pull-left">
<ul><li data-bind="css: { disabled: pageIndex() === 0 }"><a href="#" data-bind="click: previousPage">Previous</a></li></ul>
<ul data-bind="foreach: allPages">
<li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.moveToPage($data.pageNumber-1); }"></a></li>
</ul>
<ul><li data-bind="css: { disabled: pageIndex() === maxPageIndex() }"><a href="#" data-bind="click: nextPage">Next</a></li></ul>
</div>
<br clear="all" />
<script id="extItems" type="text/html">
<tr>
<td style="width:20px;" data-bind="text: extension"></td>
<td data-bind="text: name"></td>
<td data-bind="text: email"></td>
<td style="width:20px;" data-bind="text: vmpin"></td>
<td data-bind="text: device"></td>
<td data-bind="text: macAddress"></td>
<td data-bind="text: shipTo"></td>
<td class="buttons">
<a class="btn" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>
<a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
</td>
</tr>
</script>
<script id="editExts" type="text/html">
<tr>
<td style="width:20px;"><input data-errorposition="b" class="required" name="extension" data-bind="value: extension" /></td>
<td><input data-errorposition="b" class="required" name="name" data-bind="value: name" /></td>
<td><input data-errorposition="b" class="required" name="email" data-bind="value: email" /></td>
<td style="width:20px;"><input data-errorposition="b" class="required" name="vmpin" data-bind="value: vmpin" /></td>
<td>
<select style="width:100px;" data-bind="options: $root.devices, optionsText: 'name', optionsValue: 'id', value: device"></select>
</td>
<td><input data-errorposition="b" name="macAddress" data-bind="value: macAddress" /></td>
<td><select style="width:100px;" data-bind="options: $root.addressList, optionsText: 'locationName', optionsValue: 'shipping_address_street', value: shipTo"></select></td>
<td class="buttons">
<a class="btn btn-success" data-bind="click: $root.save" href="#" title="save"><i class="icon-ok"></i></a>
<a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
</td>
</tr>
</script>
</form>
<form id="extMngForm">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Extension</th>
<th>Name</th>
<th>Email</th>
<th>Voicemail Pin</th>
<th>Device</th>
<th>MAC Address</th>
<th>Ship To</th>
<th style="width: 100px; text-align:right;" />
</tr>
</thead>
<tbody data-bind=" template:{name:templateToUse, foreach: pagedList }"></tbody>
</table>
<!-- ko if: pagedList().length < extQty() -->
<p class="pull-right"><a class="btn btn-primary" data-bind="click: $root.add" href="#" title="edit"><i class="icon-plus"></i> Add Extension</a></p>
<!-- /ko -->
<div class="pagination pull-left">
<ul><li data-bind="css: { disabled: pageIndex() === 0 }"><a href="#" data-bind="click: previousPage">Previous</a></li></ul>
<ul data-bind="foreach: allPages">
<li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.moveToPage($data.pageNumber-1); }"></a></li>
</ul>
<ul><li data-bind="css: { disabled: pageIndex() === maxPageIndex() }"><a href="#" data-bind="click: nextPage">Next</a></li></ul>
</div>
<br clear="all" />
<script id="extItems" type="text/html">
<tr>
<td style="width:20px;" data-bind="text: extension"></td>
<td data-bind="text: name"></td>
<td data-bind="text: email"></td>
<td style="width:20px;" data-bind="text: vmpin"></td>
<td data-bind="text: device"></td>
<td data-bind="text: macAddress"></td>
<td data-bind="text: shipTo"></td>
<td class="buttons">
<a class="btn" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>
<a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
</td>
</tr>
</script>
<script id="editExts" type="text/html">
<tr>
<td style="width:20px;"><input data-errorposition="b" class="required" name="extension" data-bind="value: extension" /></td>
<td><input data-errorposition="b" class="required" name="name" data-bind="value: name" /></td>
<td><input data-errorposition="b" class="required" name="email" data-bind="value: email" /></td>
<td style="width:20px;"><input data-errorposition="b" class="required" name="vmpin" data-bind="value: vmpin" /></td>
<td>
<select style="width:100px;" data-bind="options: $root.devices, optionsText: 'name', optionsValue: 'id', value: device"></select>
</td>
<td><input data-errorposition="b" name="macAddress" data-bind="value: macAddress" /></td>
<td><select style="width:100px;" data-bind="options: $root.addressList, optionsText: 'locationName', optionsValue: 'shipping_address_street', value: shipTo"></select></td>
<td class="buttons">
<a class="btn btn-success" data-bind="click: $root.save" href="#" title="save"><i class="icon-ok"></i></a>
<a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
</td>
</tr>
</script>
</form>
window.ExtListViewModel = new function () {
var self = this;
window.viewModel = self;
self.list = ko.observableArray();
self.pageSize = ko.observable(10);
self.pageIndex = ko.observable(0);
self.selectedItem = ko.observable();
self.extQty = ko.observable();
self.devices = ko.observableArray(['devices']);
self.addressList = ko.observableArray(['addressList']);
self.edit = function (item) {
if($('#extMngForm').valid()) {
self.selectedItem(item);
}
};
self.cancel = function () {
self.selectedItem(null);
};
self.add = function () {
if($('#extMngForm').valid()) {
var newItem = new Extension();
self.list.push(newItem);
self.selectedItem(newItem);
self.moveToPage(self.maxPageIndex());
}
};
self.remove = function (item) {
if (confirm('Are you sure you wish to delete this item?')) {
self.list.remove(item);
if (self.pageIndex() > self.maxPageIndex()) {
self.moveToPage(self.maxPageIndex());
}
}
$('.error').hide();
};
self.save = function () {
if($('#extMngForm').valid()) {
self.selectedItem(null);
};
};
self.templateToUse = function (item) {
return self.selectedItem() === item ? 'editExts' : 'extItems';
};
self.pagedList = ko.dependentObservable(function () {
var size = self.pageSize();
var start = self.pageIndex() * size;
return self.list.slice(start, start + size);
});
self.maxPageIndex = ko.dependentObservable(function () {
return Math.ceil(self.list().length / self.pageSize()) - 1;
});
self.previousPage = function () {
if (self.pageIndex() > 0) {
self.pageIndex(self.pageIndex() - 1);
}
};
self.nextPage = function () {
if (self.pageIndex() < self.maxPageIndex()) {
self.pageIndex(self.pageIndex() + 1);
}
};
self.allPages = ko.dependentObservable(function () {
var pages = [];
for (i = 0; i <= self.maxPageIndex() ; i++) {
pages.push({ pageNumber: (i + 1) });
}
return pages;
});
self.moveToPage = function (index) {
self.pageIndex(index);
};
};
ko.applyBindings(ExtListViewModel, document.getElementById('extMng'));
function Extension(extension, name, email, vmpin, device, macAddress, shipTo){
this.extension = ko.observable(extension);
this.name = ko.observable(name);
this.email = ko.observable(email);
this.vmpin = ko.observable(vmpin);
this.device = ko.observable(device);
this.macAddress = ko.observable(macAddress);
this.shipTo = ko.observable(shipTo);
}
答案 0 :(得分:3)
在不知道标记或视图模型的样子的情况下,我假设您正在映射您的设备。我将映射以下“设备”对象并使用它。更具体地说,我必须在JSBin中看到你的代码。
var Device = function(data) {
var self = this;
ko.mapping.fromJS(data, { }, self);
// self.name added via mapping
// self.quantity added via mapping
self.numberOfDevicesShown = ko.observable();
self.showDevice = ko.computed(function(){ // use this property in the markup
return self.numberOfDevicesShown() >= self.quantitity();
})
};
var viewModelMapping = {
'devices': {
create: function(options) {
return new Device(options.data);
}
};
var ViewModel = function(data) {
var self = this;
ko.mapping.fromJS(data,viewModelMapping,self);
}
$(document).ready(function () {
vm = new ViewModel(initialViewModelData);
ko.applyBindings(vm);
});
在您的标记中,您可以执行以下操作:
<select data-bind="foreach: devices">
<!-- ko if: showDevice -->
<option></option>
<!-- /ko -->
</select>
您可以使用“创建”和使用“更新”自定义对象更新部分here
,详细了解自定义对象构建中的映射答案 1 :(得分:1)
这是一种基于在主viewmodel对象上添加可用设备的新计算的方法,以及辅助函数。它并不适用于所有情况,并且可能有简化方法,但我现在已经没有果汁了:P
self.availableDevices = ko.computed(function() {
var usedQuantities = {}; // for each device id, store the used quantity
ko.utils.arrayForEach(self.list(), function(item) {
var device = item.device();
if (device) {
usedQuantities[device.id] = 1 + (usedQuantities[device.id] || 0);
}
});
return ko.utils.arrayFilter(self.devices(), function(device) {
var usedQuantity = usedQuantities[device.id] || 0;
return device.quantity > usedQuantity;
});
});
// need this to add back item's selected device to its device-options,
// and to maintain original order of devices
self.devicesForItem = function(item) {
var availableDevices = self.availableDevices();
return ko.utils.arrayFilter(self.devices(), function(device) {
return device === item.device() || availableDevices.indexOf(device) !== -1;
});
}
和相应的绑定(注意:不使用optionsValue):
<select style="width:100px;" data-bind="options: $root.devicesForItem($data), optionsText: 'name', value: device"></select>
更新了JSFiddle:http://jsfiddle.net/antishok/QTUqD/6/
我对你的小提琴进行了一些其他微小的改动,所以它可以工作:将extQty更改为20,添加示例设备,固定元素ID为ko.applyBindings,评论表单验证的东西......可能还有几个; p(也包括在内)不同的bootstrap css)