我试图找出如何根据observableArray()中是否存在特定项目来更改表格中按钮的可见性。
例如,我有一个学生/课程名单,其中列出了所有学生和每个课程的注册学生名单。如果学生出现在当前的EnrolledStudents observableArray中,我想让所有学生列表旁边的“添加”按钮变为不可见。在我看来,我有:
<tbody data-bind="foreach: AllStudents">
<tr>
<td><button data-bind="click: $parent.add, visible: $parent.isEnrolled">Add</button></td>
<td data-bind="text: StudentId"></td>
<td data-bind="text: FirstName"></td>
<td data-bind="text: LastName"></td>
</tr>
</tbody>
我遍历AllStudents并显示信息以及“添加”按钮。但是,我有一个isEnrolled函数来确定特定学生是否在当前选定的课程中注册。这是我的功能:
this.isEnrolled = ko.computed(function (item) {
var index = $.inArray(item, self.EnrolledStudents);
if (index > -1) {
return true;
}
return false;
});
事实是,ko.computed()没有按照预期将关联的对象传递给这个函数,这使得item = undefined
...我需要做些什么来使这个函数适用于每个学生在桌子上?
这是我的整个ViewModel ..没有jsFiddle导致ajax调用无效。
function AppViewModel() {
this.AllStudents = ko.observableArray();
this.AllCourses = ko.observableArray();
this.EnrolledStudents = ko.observableArray();
this.CurrentCourse = ko.observable("1");
var self = this;
this.add = function (item) {
$.post('/api/Course/AddStudentToCourse?courseId='+self.CurrentCourse()+'&studentId='+item.Id, function (data) {
alert("Success");
console.log(data);
self.EnrolledStudents.push(data);
});
}
this.remove = function (item) {
$.ajax({
url: '/api/Course/DeleteStudentFromCourse?courseId='+self.CurrentCourse()+'&studentId='+item.Id,
type: 'DELETE',
success: function (data) {
if (data == true) {
self.EnrolledStudents.destroy(item);
}
}
});
}
this.isEnrolled = ko.computed(function () {
var index = $.inArray(item, self.EnrolledStudents);
if (index > -1) {
return true;
}
return false;
}, this);
$.get('/api/Course/AllStudents', this.AllStudents);
$.get('/api/Course/AllCourses', this.AllCourses);
$('select').change(function () {
self.CurrentCourse($('select option:selected').val());
if (self.CurrentCourse() != "") {
$.get('/api/Course/StudentsByCourse', { id: self.CurrentCourse() }, self.EnrolledStudents);
}
});
}
ko.applyBindings(new AppViewModel());
答案 0 :(得分:2)
visible
绑定默认情况下不会将当前对象作为参数传递,如click
绑定。你需要做的是这样的事情:
<tbody data-bind="foreach: AllStudents">
<tr>
<td><button data-bind="click: $parent.add, visible: $parent.checkIsEnrolled( $data )">Add</button></td>
<td data-bind="text: StudentId"></td>
<td data-bind="text: FirstName"></td>
<td data-bind="text: LastName"></td>
</tr>
</tbody>
然后将此函数添加到视图模型以验证当前对象是否已注册:
self.checkIsEnrolled = function( item ) {
var index = self.EnrolledStudents.indexOf( item );
if (index > -1) {
return false;
}
return true;
}
与可见内容无关的另一个问题是,删除功能应该实际使用remove
方法而不是destroy
。
这是使用此功能的更新小提琴:
上下文变量的完整列表如下:
答案 1 :(得分:1)
* 对Matt的问题不是一个合适的答案,因为它不符合他检索注册学生的方式 - 我已将此留在此处以获取兴趣,请参阅评论* *** 强>
作为替代方案(因为它实现了目标并保持干净),您可以在首次创建AllStudents可观察数组时向学生添加isEnrolled observable属性:
this.AllStudents=ko.observableArray(ko.utils.arrayMap(students,function(student){
student.isEnrolled = ko.observable(false);
return student;
}));
然后,当您单击“添加”时,将isEnrolled属性设置为true:
this.add = function (item) {
item.isEnrolled(true);
self.EnrolledStudents.push(item);
}
表格行上的html将如下工作:
<tr data-bind="visible:!isEnrolled()">
最后在你的删除点击中,将isEnrolled设置为false(并使用.remove(item)而不是在他的回答中由hereswhatIdid指出的destroy:
this.remove = function (item) {
item.isEnrolled(false);
self.EnrolledStudents.remove(item);
}
可以在这里找到小提琴:http://jsfiddle.net/jiggle/823v5/
希望它有所帮助。