取消选中 for 循环 KnockoutJS 中的复选框

Deselect checkboxes in for loop KnockoutJS

我试图根据结果取消选择每个选中的复选框,但我收到一条错误消息,指出 boolean is not a function

ViewModel

function IndexVM() {
    // Observable objects
    this.Files = ko.observableArray([]);

    this.CreateAML = function () {
        var self = this;

        for (var i = 0; i < self.Files().length; i++) {
            if (self.Files()[i].Selected) {
               $.ajax({
                   type: "POST",
                   url: "Home/CreateAML",
                   dataType: 'json',
                   data: "{ 'File': " + ko.toJSON(self.Files()[i]) + "}",
                   contentType: "application/json",
                   success: function (response) {
                       self.Files()[i].Selected(response.d); //this is where the error is thrown
               }
            }

   };
};

更新:

function File() {
    var self = this;
    self.Selected = ko.observable(false);
    // ...more properties
};

function IndexVM() {
    var self = this;

    // Observable objects
    self.Path = ko.observable();
    self.Files = ko.observableArray([]);

    self.selectedFiles = ko.computed(function () {
        return ko.utils.arrayFilter(self.Files(), function (file) {
            return file.Selected();
        });
    });

    this.CreateAML = function () {
       var self = this;

       ko.utils.arrayForEach(self.selectedFiles(), function (file) {
           $.ajax({
               url: "Home/CreateAMLTest",
               contentType: "application/json; charset=utf-8",
               data: ko.toJSON({
                   File: ko.toJS(file)
               })
           }).done(function (response) {
               file.Selected(response.d);
           }).fail(function (jqXHR, textStatus, errorThrown) {
               // handle the error
           });
        });
    };
};

那是因为您的 File.Selected 在您的代码中不是可观察的,它是一个普通的布尔值。

要么让它可见,要么使用 self.Files()[i].Selected = response.d; 来设置它。我建议前者。

我还建议对您的代码进行一些其他更改:

function File() {
    var self = this;
    self.Selected = ko.observable(false);
    // ...more properties
}

function IndexVM() {
    var self = this;

    self.Files = ko.observableArray([]);

    self.SelectedFiles = ko.pureComputed(function () {
        return ko.utils.arrayFilter(self.Files(), function (file) {
            return file.Selected();
        });
    });

    this.CreateAML = function () {
        ko.utils.arrayForEach(self.SelectedFiles(), function (file) {
            $.ajax({
                type: "POST",
                url: "Home/CreateAML", 
                contentType: "application/json; charset=utf-8",
                data: ko.toJSON({
                    File: ko.toJS(file)
                })
            }).done(function (response) {
                file.Selected(response.d);
            }).fail(function (jqXHR, textStatus, errorThrown) {
                // handle the error
            });
        });
    };
}

备注:

  • File.Selected 现在是可观察的。
  • 为了方便起见,现在有一个 SelectedFiles() 计算器,我想您在其他地方也需要它。如果你不这样做,它仍在改进 CreateAML().
  • 的语义
  • 我从 for 循环切换到 ko.utils.arrayForEach()。这样做对 CreateAML() 以及 creating functions in a loop (like the callbacks to .ajax()) is not recommended in JavaScript 的可读性也有积极影响。 (顺便说一下,您对这种反模式的使用最好地证明了这一点 - 您在回调中引用了 i,但在回调运行时,i 不再包含您的内容认为它包含。即使没有您遇到的错误,您的循环也不会正确运行。)
  • 通过连接字符串构建 JSON 并不理想。使用纯方法更好 (ko.toJSON({ File: ko.toJS(file) }).
  • 我在 Ajax 调用中从 "success" 回调切换到 "deferred" 语义。
  • 如果您不想手动将所有对象映射到它们的视图模型,请查看 knockout's mapping plugin
  • 根据绝大多数广泛采用的约定,只有 构造函数 名称在 JavaScript 中为 PascalCase,所有其他标识符在 camelCase 中。所以它将是 IndexVM,但是 createAMLfilesselectedFiles。考虑转行。