2012-12-30 50 views
2

我在每行數據中都有一個selectall toggle複選框和複選框。ajax調用成功後將viewmodel綁定到ui敲除

現在從服務器返回的數據不具有isSelected可觀察。我爲每一行添加了「isSelected」可觀察值。但isSelected可觀察不會綁定到每一行中的複選框。

這裏是視圖模型:

var folderViewModel = function() { 
    var self = this; 
    self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam']; 
    self.SelectedFolder = ko.observable(); 
    self.Mails = ko.observableArray([]); 
    self.SelectedMail = ko.observable(); 
    self.SelectAll = ko.observable(false); 

    self.navigate = function (folder) { 
     self.SelectedFolder(folder); 
     //$.get('/Api/MailBox', { folder: folder }, self.Mails); 

     $.ajax({ 
      url: "/Api/Mailbox", 
      data: { folder: folder }, 
      success: function (data) { 
       ko.mapping.fromJS(data, {}, self.Mails); 
       ko.utils.arrayForEach(self.Mails(), function (mail) { 
        mail.isSelected = ko.observable(true); 
        mail.isSelected.subscribe(function (myvalue) { 
         console.log(myvalue); 
        }); 
       }); 
       console.log(ko.toJSON(self.Mails())); 
      }, 
      statusCode: { 
       404: function() { 
        alert("No Mail"); 
       } 
      } 
     }); 

     //ko.mapping.fromJS(data, {}, self.Mails); 
     //console.log(ko.toJSON(self.Mails)); 
    }; 

    self.SelectAll.subscribe(function (newValue) { 
     ko.utils.arrayForEach(self.Mails(), function (mail) { 
      console.log(mail.isSelected()); 
      mail.isSelected(newValue); 

     }); 
     console.log(newValue); 
    }, self); 

    this.navigate("Inbox"); 
}; 
ko.applyBindings(new folderViewModel()); 

這裏是綁定。

<table class="table table-bordered table-striped table-condensed table-hover"> 
<thead> 
    <tr> 
     <th> 
      <input type="checkbox" data-bind="checked: SelectAll"/> 
      @*<input type="checkbox" />*@ 
     </th> 
     <th> 
      From 
     </th> 
     <th> 
      To 
     </th> 
     <th> 
      Subject 
     </th> 
     <th> 
      Date 
     </th> 
    </tr> 
</thead> 
<tbody data-bind="foreach:Mails"> 
    <tr data-bind="click:$root.navigateToMail"> 
     <td style="width: 15px"> 
      <input type="checkbox" data-bind="checked: $root.isSelected"> 
      @*<input type="checkbox">*@ 
     </td> 
     <td data-bind="text: From"> 
     </td> 
     <td data-bind="text: To"> 
     </td> 
     <td data-bind="text: Subject"> 
     </td> 
     <td data-bind="text: MailDate"> 
     </td> 
    </tr> 
</tbody> 

複選框<input type="checkbox" data-bind="checked: $root.isSelected">不獲取綁定到AJAX數據mails.isSelected=ko.obsevable(true)。可能是什麼問題?

回答

4

首先,kuddos使用learn.knockoutjs.com示例,令人驚歎的資源。

您的錯誤是KnockoutJS中的一個常見錯誤:您正在修改模型而不更新綁定到它的observables。請參閱下面的線 -

ko.mapping.fromJS(data, {}, self.Mails); 
ko.utils.arrayForEach(self.Mails(), function (mail) { ... }); 

如果你看到,你第一次創建您的郵件模型,然後添加一個額外的觀測。這個觀察值應該附加到哪個上下文中?在不更新每封郵件的值的情況下,您的mail.isSelected永遠不會添加到郵件對象。

有解決這個方法有兩種。第一個,你在foreach數組中更新郵件模型:

ko.utils.arrayForEach(self.Mails(), function (mail, index) { 
    // Add up the isSelected observable 
    self.Mails()[index] = mail; 
}); 

這對觀察到的數組,你可以閱讀here一個性能缺陷。基本上,你想要創建一個臨時數組並且每次更新整個可觀察數組,而不是每次調用Mails()

另一種方法是相當簡單:交換你是如何創建的郵件模式的順序:

ko.utils.arrayForEach(self.Mails(), function (mail) { ... }); 
ko.mapping.fromJS(data, {}, self.Mails); 

首先,你要附加一個數據對象的觀察到的,然後你告訴你的視圖模型「嘿!我們有一個新的模型來保存它有data這個屬性加上一個可觀察的isSelected我剛剛添加,小心綁定它?

話雖這麼說,在HTML屬性是checked: isSelected而不是checked: $root.isSelected,這就是爲什麼它被排序在全選(在某種程度上)工作的原因,因爲isSelected正在綁定您的視圖模型,而不是你的郵件模型。你可以有這個方便聲明弄明白調試:

// In any row inside your data 
<td data-bind="text: ko.toJSON($data)">DEBUG DATA</td> 

這應該是它,你可以看到你的代碼在這裏工作,以及其所有的解決方案:http://jsfiddle.net/jjperezaguinaga/VTuHA/。我添加了一些示例數據(來自JsFiddle的/echo/json/功能),並刪除了一些內容,以及我用來調試最後一個代碼的額外列。在最後一列中,您可以看到每次點擊複選框時更新的值爲isSelected

+0

優秀的答案,但是要小心解釋一部分。我認爲你實際上將可觀察屬性附加到數據上,然後用敲除映射來映射它。對不起,雖然noob,但他們都不是同一件事?如果你先創建一個可觀察數組,然後附加observable屬性(這顯然是我所做的,但沒有工作)。所以請謹慎解釋我的錯在這裏? – Joy

+0

沒問題,也沒有noob問題:)有一件事是ViewModel(想想你的整個函數對象,一個是用'$ root'標記訪問的,另一個是你的Mail Model,它只是一個表達式來描述你的ViewModel有一個郵件模型的集合(ko.observableArray);你的問題是你綁定了isSelected到你的ViewModel('$ root.isSelected'工作),而你需要綁定它給每個郵件模型和合適的範圍 – jjperezaguinaga

+0

這與Javascript中着名的'this'這個詞有關,當你將它附加到Mail的foreach對象時,ko.observable的上下文是什麼?它是ViewModel,所以你將它綁定到你的整個ViewModel而不是你想要的Model。Btw,Model只是一個從Backbone複製而來的語法,代表一個「類」,它在KnockoutJS中並沒有真正使用;希望這個詞的使用幫助你看到你的郵件是一個sp ecific從一個特定的類對象,而不是混淆你:) – jjperezaguinaga

0

是不是isSelected增加在每個mail項目,而不是在root視圖模型?如果是這樣的結合應該僅僅是:

<input type="checkbox" data-bind="checked: isSelected"> 

注:我還沒有看到一個navigateToMail方法在root視圖模型可用,這也將導致問題。

+0

我居然這樣做了。但是它說的是被選中沒有定義 – Joy