2013-02-14 148 views
0

想象一下按姓名排序的聯繫人數組。 這個陣列可以像被輸出:在foreach循環中分配值

<ul data-bind="foreach: contacts> 
    <li data-bind="text: name"></li> 
</ul> 

我想要做的是指定具有不同的起始字母每個L1的前進方向,所以例如顯示A,B,d ...

- A 
- Anderson 
- Andrews 
- B 
- Bellamy 
- D 
- Davidson 
- Davis 

在正常的編程語言,我會定義一個變量包含名稱的第一個字母,並檢查foreach循環裏面,看它是否是不同的。如果是這種情況,請顯示標題。

我應該如何用knockout.js做到這一點?

回答

1

這裏的那支淘汰賽模式的方法。首先,您將創建一個計算的觀察值,將您的數組映射到按字母分組的新數組中。

self.contactsByLetter = ko.computed(function() { 
    var result = [], 
     currentLetter, currentGroup; 
    ko.utils.arrayForEach(self.contacts(), function (contact) { 
     if (contact.name[0] !== currentLetter) { 
      currentLetter = contact.name[0]; 
      currentGroup = { 
       letter: currentLetter, 
       contacts: [] 
      } 
      result.push(currentGroup); 
     } 
     currentGroup.contacts.push(contact); 
    }) 
    return result; 
}); 

然後你的HTML只需要兩個循環。

<ul data-bind="foreach: contactsByLetter"> 
    <li class="heading" data-bind="text: letter"></li> 
    <!--ko foreach: contacts--> 
    <li data-bind="text: name"></li> 
    <!--/ko--> 
</ul> 

的jsfiddle:http://jsfiddle.net/mbest/ZcQT4/

0

不知道它是清潔的方式,但你可以使用一個固定的數組的字母,然後在您的視圖模型的方法只返回開頭的第n個字母的項目 - 即

<ul data-bind="foreach: letters"> 
    <li data-bind="text: $data"> 
     <ul data-bind="foreach: $parent.contactsStartingWith($data)"> 
      <li data-bind="text: name"></li> 
     </ul> 
    </li> 
</ul> 

哪裏contactsStartingWith可以像來定義:

function(start) { 
    return ko.utils.arrayFilter(contacts(), function(it) { return it.name()[0].toUpperCase() == start }); 
} 

...和字母陣列可以容易地提取爲:

viewModel.letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); 

(用於處理數組淘汰賽utils的一些有用的參考資料:http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html

+0

我認爲邁克爾的建議是更好,因爲它也將避免「空」的標題。例如。如果沒有與第一個字母Q的聯繫。感謝您的回覆。 – 2013-02-15 07:29:45

+0

我同意,它也更容易處理(所有東西都捆綁在一個可觀察對象內) - 事實上,我也投了贊成票:) – Grim 2013-02-15 08:20:08