好吧,我有工作代码,通过选中的复选框删除选定的行。但是我遇到了强制执行的问题,在任何给定时刻只能检查其中一个单选按钮。我的第一种方法是将click事件与每个单选按钮绑定,如果单击它,它将遍历可观察数组并标记所有" false。"然后,它只是将标志翻转为true,以触发事件。我知道这不是最好的方式,但是我对淘汰赛缺乏光彩的知识迫使我走上这条道路......尽管这种方法并不适合我。任何人都可以阐明我做错了什么或如何正确地解决这个问题?
表的html
<table class="accountGroups information" id="tblAccountGroups">
<tr>
<td width="125px;" style="font-weight: bold;">StandardAccountNo</td>
<td width="125px;" style="font-weight: bold; text-align: center;">Primary</td>
<td style="font-weight: bold;">Effective Date</td>
<td style="font-weight: bold;">End Date</td>
<td style="font-weight: bold;">Remove</td>
</tr>
<!-- ko foreach: NewAccountGroupDetails-->
<tr id="Model.NewAccountGroupDetails[0].AccountGroupName" class="acctgrp-row">
<td>
<div>
<input style="width: 100%;" data-bind="value: StandardAccountNo, attr: {name: 'NewAccountGroupDetails[' + $index() + '].StandardAccountNo'}" />
</div>
</td>
<td>
<div style="text-align:center;">
<input style="width:100%;" type="radio" data-bind="value: IsPrimary, attr: {name: 'NewAccountGroupDetails[' + $index() + '].IsPrimary'}, click: $parent.markIsPrimary" />
</div>
</td>
<td>
<div>
<input style="width:125px;" class="datepicker" data-bind="value: EffectiveDate, attr: {name: 'NewAccountGroupDetails[' + $index() + '].EffectiveDate'}" readonly="readonly" />
</div>
</td>
<td>
<div>
<input style="width:125px;" class="datepicker" data-bind="value: EndDate, attr: {name: 'NewAccountGroupDetails[' + $index() + '].EndDate'}" readonly="readonly" />
</div>
</td>
<td>
<div style="text-align:center;">
<input type="checkbox" data-bind="checked: markedForDeletion, attr: {name: 'NewAccountGroupDetails[' + $index() + '].MarkedForDeletion'}" />
</div>
</td>
</tr>
<!-- /ko -->
</table>
以下JS为页面提供支持
////VIEW MODEL FOR KNOCKOUT////
var Detail = function () {
this.StandardAccountNo = ko.observable('');
this.IsPrimary = ko.observable(false);
this.EffectiveDate = ko.observable(formattedDate(new Date()));
this.EndDate = ko.observable(formattedDate(new Date()));
this.markedForDeletion = ko.observable(false);
};
var ViewModel = function () {
var rawList = '@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.NewAccountGroupDetails))';
this.NewAccountGroupDetails = ko.observableArray(convertJSONToKoObservableObject($.parseJSON(rawList)));
this.NewAccountGroupDetails.push(new Detail());
this.deleteMarkedItems = function () {
this.NewAccountGroupDetails.remove(function (item) {
return item.markedForDeletion();
});
};
this.markIsPrimary = function () {
for (i = 0; this.NewAccountGroupDetails().length > 0; i++) {
this.NewAccountGroupDetails[i].IsPrimary(false);
}
return item.IsPrimary(true);
};
this.addNew = function () {
this.NewAccountGroupDetails.push(new Detail());
$('.datepicker').each(function (i, obj) {
$(obj).datepicker({ changeYear: true, changeMonth: true });
});
}
};
ko.applyBindings(new ViewModel());
function convertJSONToKoObservableObject(json) {
var ret = [];
$.each(json, function (i, obj) {
var newOBJ = {};
for (prop in obj) {
newOBJ[prop] = ko.observable(obj[prop]);
}
ret.push(newOBJ);
});
return ret;
}
一旦我按照我想要的方式运行页面,我将研究语法改进,例如数组的ko映射库。
答案 0 :(得分:2)
在视图模型中,构造如下的删除按钮:
viewModel.remove = function (row) {
console.log(row);
viewModel.NewAccountGroupDetails.remove(row);
};
现在,当前上下文作为第一个参数传递给knockout中的任何回调。因此,如果您添加一个带有data-bind="click: $parent.remove"
的按钮,它将使用行上下文调用viewModel.remove
函数。
<tr ...>
...
<td>
<button data-bind="click: $parent.remove">Remove</button>
</td>
</tr>
答案 1 :(得分:1)
我需要一些额外的信息,但是让我给你举个例子,并给你一些建议:
首先,建议:
var JSON=*your serialized JSON*;
(不要忘记末尾的分号。NewAccountGroupDetails['+ $index() + '].EndDate
,对viewmodel本身进行此计算,使用计算名称,例如EndDateName
selectedRow
可观察对象。当用户选择行时,将行放在那里,您可以使用计算的observable来确定行是否是所选行。2的例子:
// Instead of:
var viewModelJson = '[{"name": "Pepe"},{"name":"Juan"}]';
var viewModel = $.parseJSON(viewModelJson);
// Do this directly:
var people = [{"name": "Pepe"},{"name":"Juan"}];
由于4和5不能立即显示,这是您想要实现的简单示例。
<ul data-bind="foreach: people">
<li data-bind="text: name, click: $root.select,
css: {red: $data == $root.selectedPerson()}" >
</li>
</ul>
请注意,当条件为true时,将应用css类red
。条件是绑定到当前行的值与selectedPerson
observable中的值相同。
这是相应的JavaScript(记得引用淘汰映射!!)
var people = [{"name": "Pepe"},{"name":"Juan"}];
var PeopleModel = function(people) {
var self = this;
self.selectedPerson = ko.observable(); // This will hold the selected person
self.people = ko.mapping.fromJS(people); // Note ko.mapping!!
self.select = function(person) { // event receives the current data as 1st param
self.selectedPerson(person);
}
self.delete = function(person) {
// find de index of person and remove 1 item from that index
self.people.splice(self.people.indexOf(person),1);
}
return self;
};
var peopleModel = new PeopleModel(people);
ko.applyBindings(peopleModel);
如果您更改点击装订以调用$root.delete
而不是$root.select
,则点击该列表时,您会看到该列表中的人员消失。当然,您可以添加额外的元素来执行此操作。
注意:您可以阅读click binding on knockout js site上的文档。
最后一条建议:使用Web API或返回JsonResult直接从服务器恢复数据的方法要好得多,并将js保存在单独的文件中。
<强>更新强> 一点点模式代码。
您可以添加此HTML:
<input type="button" data-bind="click: removeSelected" value="removeSelected"/>
在视图模型中使用此方法:
self.removeSelected = function() {
if (self.selectedPerson()) {
self.delete(self.selectedPerson());
}
};
如果这样做,当点击按钮时,如果有所选项目,它将从列表中删除。
这里有一个更完整的示例in this fiddle,其中包含以下代码:
CSS:
body {
font-family: Arial;
}
.container {
margin: 10px 0;
border: solid 1px #ABF;
}
.container > div {
padding: 4px;
border: solid 1px #ABF;
position: relative;
}
.selected {
border: solid 1px #00A;
color: #00A;
background-color: #BCF;
}
HTML:
<div data-bind="foreach: people" class="container">
<div data-bind="click: $root.select,
css: {selected: $data == $root.selectedPerson()}" >
<!-- ko text: name --><!-- /ko -->
<input type="button" value="Remove"
style="right:3px;top:2px; position:absolute;"
data-bind="click:$root.delete"/>
</div>
</div>
<div data-bind="visible: selectedPerson()" >
<input type="button" data-bind="click: removeSelected" value="Remove Selected"/>
<input type="button" data-bind="click: unSelect" value="Deselect"/>
</div>
<div data-bind="visible: selectedPerson()" class="container">
<div>
Selected: <!-- ko text: selectedPerson().name --><!-- /ko -->
</div>
</div>
JavaScript的:
var people = [{"name": "Pepe"},{"name":"Juan"},{"name":"Luis"},{"name":"Adolfo"}];
var PeopleModel = function(people) {
var self = this;
self.selectedPerson = ko.observable(); // This will hold the selected person
self.people = ko.mapping.fromJS(people); // Note ko.mapping!!
self.select = function(person) { // The event receives the current data as parameter
self.selectedPerson(person);
};
self.delete = function(person) {
// find de index of person and remove (splice) it from the observable array
self.people.splice(self.people.indexOf(person),1);
self.selectedPerson(null);
}
self.removeSelected = function() {
if (self.selectedPerson()) {
self.delete(self.selectedPerson());
}
};
self.unSelect = function() {
self.selectedPerson(null);
}
return self;
};
var peopleModel = new PeopleModel(people);
ko.applyBindings(peopleModel);
答案 2 :(得分:0)
尝试在选择时暂时保存所选行
function AccountGroupViewModel() {
var viewModel = this;
viewModel.selectedRow = null;
// ...
viewModel.selectRow = function (data) {
// ...
viewModel.selectedRow = data;
}
viewModel.remove = function () {
// ...
if (viewModel.selectedRow != null) {
this.NewAccountGroupDetails.remove(viewModel.selectedRow);
}
}
}