1

In my ViewModel I have the following method that returns me the css class depending on pState:

function MyViewModel()
{
    var self = this;

    self.GetClass = function(pState) 
    {
        var lCssClass;

        switch(pState)
        {
            case "warning": 
                lCssClass = 'bg-yellow';
                break;
            case "red":
                lCssClass = 'font-red';
                break;
            default:
                lCssClass = 'font-default';
                break;
        }

        return lCssClass;
    };
}

I want to add the class in my view:

<span class="list-item" data-bind="attr : { class : $root.GetClass('warning')}">This is a warning.</span>

My problem: the existing class list-item will be overridden.

Here is a fiddle: http://jsfiddle.net/d8L6v9h7/

2 Answers 2

2

The css binding will preserve existing classes. Use it e.g. like this:

function MyViewModel()
{
    var self = this;
  
    self.GetClass = function(pState) 
    {
        var lCssClass;

        switch(pState)
        {
            case "warning": 
                lCssClass = 'bg-yellow';
                break;
            case "red":
                lCssClass = 'font-red';
                break;
            default:
                lCssClass = 'font-default';
                break;
        }

        return lCssClass;
    };
}

ko.applyBindings(new MyViewModel());
.list-item:before { content: ' ✓ '; } /* Just to prove it's preserved. */
.bg-yellow { background-color: yellow; }
.font-red { color: red; }
.font-default { }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<span class="list-item" data-bind="css: $root.GetClass('warning')">This is a warning.</span>

This is a "straight up" answer to your question. Please also check @Progrindis answer and even consider going a few steps further than that in inverting the way your code work.

PS. If you want an even more "straight up" solution, for example for when you're creating a quick mock up and don't care about neatness of the solution, you can also resort to:

<span data-bind="attr: { class: 'list-item ' + $root.GetClass('warning') }">
Sign up to request clarification or add additional context in comments.

3 Comments

Wouldnt it be better to at least use a computed observable ? From my understanding this GetClass would need to be called each time in order to get updated value.. Defeating the purpose of an observable no ?
Yes, I agree that there are some code smells that probably need to be addressed (in manners you suggest). However, OP hasn't quite posted enough of his/her setup to be able to do a code review c.q. suggest alternatives without resorting to guessing. This is why I answered the question straight up.
As such I'd wish @Benoît would undelete his answer so I can upvote it :), it's an even more straight-up answer, well-suited for someone "just wanting to get things working" (e.g. when creating a quick mock-up I think such an approach can be warranted).
1

You use the css binding..

KnockoutJS CSS Binding

For example :

<div data-bind="css: { profitWarning: currentProfit() < 0 }">
   Profit Information
</div>

<script type="text/javascript">
    var viewModel = {
        currentProfit: ko.observable(150000) // Positive value, so initially we don't apply the "profitWarning" class
    };
    viewModel.currentProfit(-50); // Causes the "profitWarning" class to be applied
</script>

you can just add the class itself or you can add conditional logic to decide when its applied.

For your example it looks like you can have lCssClass as an observable and apply this to your html :

var self = this,
classObservable = ko.observable("");

switch(pState)
        {
            case "warning": 
                self.classObservable('bg-yellow');
                break;
            case "red":
                self.classObservable('font-red');
                break;
            default:
                self.classObservable('font-default');
                break;
        }

Then in your HTML :

<span class="list-item" data-bind="css: classObservable()">This is a warning.</span>

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.