Tweak your sort function. In OO fashion, the "All" object would have a property that indicates that it should be ordered at the top. Alternatively, the quick and dirty way to go is to tweak your sort function to something like this:
function (l, r) {
if (l.name === "All") return 1;
if (r.name === "All") return -1;
return l.name().localeCompare(r.name());
}
I think I got the +1/-1 logic right, but you've got unit tests to work out those details, right? ;)
As a side note, I'd use the localeCompare function to compare strings.
Seconding @MattBurland's comment, you should move the sorting logic to your View Model too (this would be required anyways to unit test it). In addition, note that sort will sort the array itself, and you can also call sort on the observable (without invoking it as a function to get the observable's value), to sort the contents of the observable.
Here's what that would look like:
function ViewModel(items) {
var self = this;
self.myArray = (items);
self.myArray.sort(function (l, r) {
if (l.name() === "All") return -1;
if (r.name() === "All") return 1;
return l.name().localeCompare(r.name());
});
};
var vm = new ViewModel([
{ name: ko.observable("B") },
{ name: ko.observable("A") },
{ name: ko.observable("All") }
]);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: myArray" class="nav nav-tabs" role="tablist">
<li data-bind="text: name"></li>
</ul>
Or like this, if you use the OO approach:
function ViewModel(items) {
var self = this;
self.myArray = (items);
self.myArray.sort(function (l, r) {
if (!!l.isSpecialOption) return -1;
if (!!r.isSpecialOption) return 1;
return l.name().localeCompare(r.name());
});
};
var vm = new ViewModel([
{ name: ko.observable("B") },
{ name: ko.observable("A") },
{ name: ko.observable("All"), isSpecialOption: true }
]);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: myArray" class="nav nav-tabs" role="tablist">
<li data-bind="text: name"></li>
</ul>
Acomes beforeAllso your sorting is correct. If you want it to sort differently then you'll have to add a clause to handleAll. But take the model logic out of your view and put it in acomputedproperty, it'll be a lot cleaner.