将表行的按钮可见性绑定到KnockoutJS中的函数

时间:2014-02-26 19:42:17

标签: knockout.js

我试图找出如何根据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());

2 个答案:

答案 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

这是使用此功能的更新小提琴:

http://jsfiddle.net/7J8XR/4/

上下文变量的完整列表如下:

http://knockoutjs.com/documentation/binding-context.html

答案 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/

希望它有所帮助。