Search code examples
knockout.jsknockout-mapping-plugin

Equals not working in Knockout


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?


Solution

  • http://jsfiddle.net/pUHEf/

    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 }