6

I use foreach on an observable array:

<div id="mainRight" data-bind="foreach: notifications">
    <div class="statusRow">
        <div class="leftStatusCell">
            <div class="leftStatusCellColor" data-bind="css: availabilityCssClass($data.availability)"></div>
        </div>
        <div class="topRightStatusCell" data-bind="text: sip"></div>
        <div class="bottomtRightStatusCell ellipsisSingleline" data-bind="text: note"></div>
    </div>
</div> <!== end mainRight ==>

As you can see, I pass the current value of availability to the function availabilityCssClass, which compares the value to some predefined strings. Depending on the matching string, it returns a class name.

self.availabilityCssClass = ko.computed(function (value) {
    var availability = value;
    if (availability === "Busy" || "DoNotDisturb" || "BeRightBack")
        return "leftStatusCellColorOrange";
    else if (availability === "Away" || "Offline")
        return "leftStatusCellColorRed";
    else
        return "leftStatusCellColorGreen";
});

This is my model. The data comes from an external data source.

function Notification(root, sip, availability, note) {
    var self = this;

    self.sip = ko.observable(sip);
    self.availability = ko.observable(availability);
    self.note = ko.observable(note);
};

self.notifications = ko.observableArray();

However, it doesnt work as is. When the computed function is not commented out, the foreach does not iterate over the data and the div is empty. But I can see that the viewModel is not empty.

4
  • 1
    Can you provide a fiddle, and describe what doesn't work. Commented Nov 19, 2012 at 12:04
  • Which KO version are you using? Commented Nov 19, 2012 at 12:04
  • Im using 2.2 so this functionality should be supported, right? Commented Nov 19, 2012 at 12:08
  • The class is not applied according to evaluated value. Commented Nov 19, 2012 at 12:13

3 Answers 3

4

You cannot pass value into computed in such way. It is better to add this computed to Notification view model and use self.availability property:

function Notification(root, sip, availability, note) {
    var self = this;

    self.sip = ko.observable(sip);
    self.availability = ko.observable(availability);
    self.note = ko.observable(note);

    self.availabilityCssClass = ko.computed(function() {
        var availability = self.availability();

        if (["Busy", "DoNotDisturb", "BeRightBack"].indexOf(availability) != -1) return "leftStatusCellColorOrange";
        else if (["Away", "Offline"].indexOf(availability) != -1) return "leftStatusCellColorRed";
        else return "leftStatusCellColorGreen";
    });
};

Your if statement wasn't correct, so I fixed the logic. Here is working fiddle: http://jsfiddle.net/vyshniakov/Jk7Fd/

Sign up to request clarification or add additional context in comments.

6 Comments

That is awesome, thank you! Why cant I pass the value to the computed function like I did? And what was wrong with the if-statement?
I don't know why but passing values to computed doesn't work :). In javascript you cannot compare value in such way you did it. In your code first 'if' will always return true when availability is not Busy.
Just noticed that the note value is overwritten each time the availability changes. How can I avoid this?
It shouldn't. Maybe there is another code in your project that does it, but didn't post it.
Yes, I have this: //Add or update with empty values supplied self.addNotification = function (sip, availability, note) { var existingItem = ko.utils.arrayFirst(self.notifications(), function (item) { return item.sip().toLowerCase() == sip }); if (existingItem) { existingItem.availability(availability); existingItem.note(note); } else { self.notifications.push(new Notification(self, sip, availability, note)); } self.notifications.sort(); };
|
1

You just need to make availabilityCssClass a function. As you've written it, it's not a computed observable since it has no observable dependencies.

self.availabilityCssClass = function (value) {
    var availability = value;
    if (availability === "Busy" || "DoNotDisturb" || "BeRightBack")
        return "leftStatusCellColorOrange";
    else if (availability === "Away" || "Offline")
        return "leftStatusCellColorRed";
    else
        return "leftStatusCellColorGreen";
};

Comments

0

The CSS binding wants a object literal with the name of the CSS class as member name and the value true or false depeding on you want to remove or add the class

data-bind="css: { 'css-class-name': true }"

edit: Hmm, they have changed the css binding in 2.2 ;)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.