I've got some problems with simple knockout application.
Model:
function ContactListVM() {
var self = this;
self.selectedContact = ko.observable("");
self.contacts = ko.observableArray([]);
self.LoadItems = function () {
$.ajax({
url: "Contacts/GetContactList/",
type: "POST",
data: { },
success: function (data) {
$.each(data.Contacts, function () {
self.contacts.push(ko.mapping.fromJS(this));
});
if (self.selectedContact() == "") {
var data = new Object();
data.ID = self.contacts()[0].ID;
self.selectContact(data, null);
}
}
});
}
self.LoadItems();
self.selectContact = function (data, event) {
$.ajax({
url: "Contacts/GetContact/",
type: "POST",
data: { ID: data.ID },
success: function (data) {
self.selectedContact(ko.mapping.fromJS(data.Contact));
}
});
}
}
So generaly I have a list of contacts with very basic info and a full model of the selected contact. The selected contact should be marked on the list with different css class:
<ul class="contact-list">
<!-- ko template: { name: 'item-template', foreach: contacts() } -->
<!-- /ko -->
<script id="item-template" type="text/html">
<li class="item" data-bind="click: $root.selectContact, css: { selected: $root.selectedContact().ID == ID() }">
<span class="contact-name" data-bind="text: Name"></span>
<span class="contact-name" data-bind="text: $root.selectedContact().ID"></span>
<span class="contact-name" data-bind="text: ID()"></span>
</li>
</script>
</ul>
Unfortunately the statement css: { selected: $root.selectedContact().ID == ID() } is not working. None of the items is selected. What is more few lines below where I bind these values to spans they appear equal on the screen. How could I fix this?
The problem was that before you selected a contact selectedContact() was empty, therefore had no method ID. You need to put an additional statement into your logic.
<script id="item-template" type="text/html">
<li class="item" data-bind="click: $root.selectContact, css: { selected: $root.selectedContact() ? $root.selectedContact().ID() === ID() : false }">
<span class="contact-name" data-bind="text: Name"></span>
<span class="contact-name" data-bind="text: $root.selectedContact().ID"></span>
<span class="contact-name" data-bind="text: ID()"></span>
</li>
</script>
This works, check the fiddle. A basic explanation -
The selected class will be applied if the following logic is true (in my own language)
if ($root.selectedContact() !== (undefined or null))
{
if ($root.selectedContact().ID() === ID())
{
set class = selected;
}
else { don't set a class }
}
else { don't set a class }