Reputation: 986
I have a template that its bound to a knockout observableArray. I'm trying to get a something to display only on the first item in the array. When the first item is deleted, the next item that becomes the first should then display this section. It should work similar to the following code. The key is the isFirst function.
HTML
<div data-bind="template: { name: 'my-template', foreach: people }"></div>
<script type="text/html" id="my-template">
<div>
<span data-bind="visible: isFirst">The first person is </span>
<span data-bind="text: name"></span>
</div>
</script>
<button data-bind="click: removeFirst">Remove First</button>
ViewModel
function Person(p,name,age) {
this.parent = p;
this.name = name;
this.age = age;
this.isFirst = ko.computed(function(){
return this.parent.people.indexOf(this) === 0;
});
}
var viewModel = function() {
var self = this;
self.people = ko.observableArray();
self.people.push(new Person(self, 'Fred', 25));
self.people.push(new Person(self, 'Joe', 15));
self.people.push(new Person(self, 'Sally', 21));
self.people.push(new Person(self, 'Ann', 37));
self.people.push(new Person(self, 'Jack', 52));
self.removeFirst = function () {
people.splice(0, 1);
}
};
};
Upvotes: 1
Views: 789
Reputation: 3118
Since you are within the context of a foreach binding you can take advantage of the $index
property detailed within the link under "Note 2 : Using $index, $parent, and other context properties"
You have a couple different options.
Use a containerless if binding
to only render markup for the first element similar to the discussion within this question
<!-- ko if: $index()=== 0 -->
<span>The first person is</span>
<!-- /ko -->
Continue to use the visible
binding to render markup for each element but only be visible on the first item
<span data-bind="visible: $index() == 0">The first person is </span>
For this particular case, option #1 is the more suitable approach.
Edit: Keeping it in the viewmodel:
I'd move isFirst
into $root, and then change the binding. Since, we already have $index
you could pass that in
<!-- ko if: $root.isFirst($index) -->
-
self.isFirst = function(index){
return 0 === index();
}
Alternatively and similar to your original approach:
<!-- ko if: $root.isFirst($data) -->
-
self.isFirst = function(item){
return 0 === self.people.indexOf(item);
}
Upvotes: 2