2015-01-12 270 views
0

我想取消已籤根據結果每個複選框,但我得到一個錯誤,說明布爾不是一個函數取消選中複選框

視圖模型

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 
      }); 
     }); 
    }; 
}; 

回答

2

這是因爲您的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調用切換到「延遲」語義學對。
  • 看那knockout's mapping plugin,如果你不希望將所有的對象手動映射到
  • 通過壓倒性的廣泛採用的慣例僅構造自己的視圖模型。名是在JavaScript PascalCase,所有其它標識符是camelCase。因此,這將是IndexVM,但createAMLfilesselectedFiles。想想切換。
+0

非常感謝您的讚賞信息。我在這一行收到錯誤「未定義不是函數」:this.selectedFiles = ko.pureComputed(function(){ – Gericke

+0

你使用的是什麼版本的knockout?如果它低於3.2,只需使用'computed()而不是'pureComputed()'。[Pure computeds](http://knockoutjs.com/documentation/computed-pure.html)已經在3.2中引入了,如果你不能使用它們,那麼不要介意和使用普通的。 – Tomalak

+0

我正在使用3.0,所以我的理解是應該工作 – Gericke