我有一个联系人列表,如:
1 Mon
Bob
Brett
Brad
Kathy
Zelda
使用KnockoutJS很容易在应用模型或使用jQuery模板后显示该列表。
我现在感兴趣的是动态显示标题,就像它在iPhone上的工作方式一样,意味着输出看起来像:
#
1 Mon
B
Bob
Brett
Brad
K
Kathy
Z
Zelda
有关如何使用Knockout巧妙地完成此操作的任何想法,而不必对每个字母数字进行硬编码?
答案 0 :(得分:4)
我在KO论坛上回答了您的问题:https://groups.google.com/d/topic/knockoutjs/VgDnxb_jB7c/discussion
此处示例:http://jsfiddle.net/rniemeyer/MZN6u/
我创建了一个dependentObservable,其结构可以轻松映射到视图(模板),这是一个对象数组,每个对象都有letter
属性和contacts
数组。
dependentObservable看起来像:
viewModel.contactsByLetter = ko.dependentObservable(function() {
var letterIndex = [];
var result = [];
//sort the contacts
var sortedContacts = this.contacts().sort(function(a, b) {
return a.name().toUpperCase() > b.name().toUpperCase() ? 1 : -1;
});
//loop through each contact and put it with its letter
ko.utils.arrayForEach(sortedContacts, function(contact) {
//grab first character
var firstLetter = contact.name().charAt(0).toUpperCase();
//if it is a number use #
if (!isNaN(firstLetter)) {
firstLetter = "#";
}
//do we already have entries for this letter
if (!letterIndex[firstLetter]) {
//new object to track this letter's contacts
var letterContacts = {
letter: firstLetter,
contacts: []
};
letterIndex[firstLetter] = letterContacts ; //easy access to it
result.push(letterContacts); //add it to the array that we will return
}
//at this point we should have an object to push our contact to
letterIndex[firstLetter].contacts.push(contact);
});
return result;
}, viewModel);
答案 1 :(得分:3)
contacts.sort();
var contactsGrouped = {};
$.each(contacts, function(index, contact) {
var first = contact.substr(0, 1),
group = first.match(/\d+/) ? '#' : first;
if (contactsGrouped[group] === undefined) {
contactsGrouped[group] = [];
}
contactsGrouped[group].push(contact);
});
如果您不确定联系人上是否有前导/尾随空格,可能值得调用$.trim()
。
此外,如果要为#
和a-z
创建空白数组,只需先遍历'#abcdefghijklmnopqrstuvwxyz'.split('')
并设置空白数组。
此外,如果您希望属性为大写,只需在设置属性之前调用toUpperCase()
方法。