抱歉这个冗长的问题。我是knockout.js的新手。
我的商业案例 我有一个面板,在foreach循环中有两个复选框(是/否)。对于某些项目组,当选中一个项目并选中“是”复选框时,我需要取消选中该组中其他项目的“是”复选框,并选中这些项目的“否”复选框。
当用户'检查'复选框时调用subscribe函数,并且由于我在上面第6点中解释的逻辑而在subscribe方法中更改了可观察数组时也调用了该函数。
问题:事情似乎工作得很好,我可以通过开发人员工具进行调试,但是当执行删除已经选择的值的逻辑时,它不会反映在UI中。复选框仍然会为组中的多个项目选择“是”。
例如:当在组中选择了其中一个项目的“是”复选框时,必须取消选中组中其他项目“是”复选框。这似乎反映在变量值中,但UI显示其他项目仍然选中“是”复选框。
包含“是”所选项目的My Observable数组仍会在其中显示正确的值(在控制台中),但UI显示多个项目选择了“是”。
请告诉我这里的问题。
HTML:
<div data-bind="template: { name: 'ItemTemplate', foreach: Items }"></div>
<script type="text/html" id="ItemTemplate">
<!-- Other Html stuffs -->
<div id="SelectionPanel" class="SelectionPanel checkStyle">
<label>
<input type="checkbox" data-bind="value: Id(), click: $root.PersistAutoSelection, checked: $root.SelectedItem, attr: { 'class': SelectStyle, id: 'itemPanelSelected' + $index(), name: 'SelectedIds'}" />
<label data-bind="attr: { 'for': 'PanelSelected' + $index() }">
<p>Yes</p>
</label>
</label>
</div>
<div id="NotRequiredPanel">
<div class="checkbox checkStyle">
<input type="checkbox" class="not-required" data-bind="value: Id(), click: $root.Deselect.bind($data, Id().toString()),checked: $root.NotRequired,attr: { id: 'PanelNotRequired' + $index(), name: 'NotRequiredIds' }" />
<label data-bind="attr: { 'for': 'PanelNotRequired' + $index() }">
<p>No</p>
</label>
</div>
</div>
</script>
Knockout.js脚本:
var currentlySelectedObject = null;
var isExcessModified = false;
function ViewModel() {
var self = this;
self.SelectedItem = ko.observableArray([]);
self.NotRequired = ko.observableArray([]);
self.Select = function (index) {
self.SelectedItem.push(index.toString());
}
self.Deselect = function (index) {
self.SelectedItem.remove(index.toString());
self.NotRequired.remove(index.toString());
self.NotRequired.push(index.toString());
return true;
}
self.SelectedItem.subscribe(function (newValue) {
var unselectedItem = ko.utils.arrayMap(self.Items(), function (item) {
return item.Id().toString();
});
ko.utils.arrayForEach(self.SelectedItem(), function (itemId) {
ko.utils.arrayRemoveItem(unselectedItem , itemId.toString());
});
if (isExcessModified)
self.ExcessProtectSelectValidation(currentlySelectedObject);
});
self.Remove = function (name) {
ko.utils.arrayForEach(self.Items(), function (item) {
if (item.Name().toLowerCase() == name.toLowerCase()) {
var itemId = item.Id().toString();
self.SelectedItem.remove(itemId);
self.NotRequired.remove(itemId);
}
});
}
self.PersistAutoSelection = function (data, event) {
self.NotRequired.remove(data.Id().toString());
if (!$('#itemPanelSelected' + data.Id().toString()).is(':checked'))
self.SelectedItem.remove(data.Id().toString());
currentlySelectedObject = event.target;
isExcessModified = true;
return true;
}
self.ExcessProtectSelectValidation = function (obj) {
isExcessModified = false;
var yesNoPanel = $(obj).closest('div.bottom');
var schId = $(obj).closest('div.bottom').prev().prev().find("[id^=SchemeID]").val();
if (schId == "AC1" || schId == "AC2" || schId == "AC3") {
//Condition to choose any one of the item
if ($(obj).is(':checked')) {
if (isExcessSelected) {
var itemId = $(obj).closest('[id^="itemPanelInner"]').attr("panelId");
//Logic to remove error message for previous selection
$('*[id*=SchID]').each(function (index) {
if ($(this).val() != schCodeId && ($(this).val() == "AC1" || $(this).val() == "AC2" || $(this).val() == "AC3")) {
Code to show tooltip here;
}
});
//Show error message if try to choose the more than one item had chosen
AddErrorToolTip(yesNoPanel, ToolTipContent);
self.NotRequired.push(itemId.toString());
self.SelectedItem.remove(itemId.toString());
}
else {
//Logic to deselect the other two item, if one the item is already selected
yesNoPanel.removeClass("ErrorHighlight");
yesNoPanel.qtip("destroy", true);
isExcessSelected = true;
if (schId == "AC1" || schId == "AC2" || schId == "AC3") {
$('*[id*=SchID]').each(function (index) {
if ($(this).val() == "AC1" || $(this).val() == "AC2" || $(this).val() == "AC3") {
var itemId = $(this).closest('[id^="itemPanelInner"]').attr("panelId");
if ($(this).val() != schId && ($(this).val() == "AC1" || $(this).val() == "AC2" || $(this).val() == "AC3")) {
var yesNoPanel = $(this).closest('div.top').next().next();
yesNoPanel.removeClass("ErrorHighlight");
yesNoPanel.qtip("destroy", true);
self.NotRequired.push(itemId.toString());
$('#itemPanelSelected' + itemId.toString()).attr('checked', false);
self.SelectedItem.remove(itemId.toString());
}
}
})
}
}
}
else {
isExcessSelected = false;
$('*[id*=SchID]').each(function (index) {
if ($(this).val() == "AC1" || $(this).val() == "AC2" || $(this).val() == "AC3") {
if ($(this).closest("div.top").next().next().find('[id^="ItemPanelNotRequired"]').is(':checked')) {
//Logic to remove the error message if already selected item is unselected
if ($(this).closest('[id^="ItemPanelInner"]').find('div.bottom.ErrorHighlight').length > 0) {
var errorAttachedPanel = $(this).closest('[id^="ItemPanelInner"]').find('div.bottom');
errorAttachedPanel.removeClass("ErrorHighlight");
errorAttachedPanel.qtip("destroy", true);
}
}
}
})
}
}
}
}