10

I am making a small app for countdown timer in which i have used knockout css binding with multiple classes. Now, the problem is if i am writing the logic in separate handler it is working fine but if trying to implement the same logic inline with css binding its not working as required.

Working version: http://jsfiddle.net/gzejF/3/

<div class="dateTimer" data-bind="timer: startTime, timerOptions: {speed: 1000}">
    <div class="tens">
        <div class="upperTensClock timerLine"></div>
        <div class="lowerTensClock timerLine"></div>
    </div>
    <div class="units">
        <div class="upperClock timerLine"></div>
        <div class="lowerClock timerLine"></div>
    </div>
</div>

Not working version: http://jsfiddle.net/K6m93/

<div class="dateTimer">
    <div class="tens">
        <div class="upperTensClock" data-bind="css: {
            'l1 l2 l3': tens() == 0,
            'l3': tens() == 1,
            'l2 l3 l7': tens() == 2 || tens() == 3,
            'l1 l3 l7': tens() == 4,
            'l1 l2 l7': tens() == 5 || tens() == 6,
            'l2 l3': tens() == 7,
            'l1 l2 l3 l7': tens() == 8 || tens() == 9 
            }"></div>

        <div class="lowerTensClock" data-bind="css: {
            'l4 l5 l6': tens() == 0 || tens() == 6 || tens() == 8,
            'l4': tens() == 1 || tens() == 4 || tens() == 7 || tens() == 9,
            'l5 l6': tens() == 2,
            'l4 l5': tens() == 3 || tens() == 5
            }"></div>

    </div>

    <div class="units">
         <div class="upperClock l1 l2 l3 l7" data-bind="css: {
            'l1 l2 l3': units() == 0,
            'l3': units() == 1,
            'l2 l3 l7': units() == 2 || units() == 3,
            'l1 l3 l7': units() == 4,
            'l1 l2 l7': units() == 5 || units() == 6,
            'l2 l3': units() == 7,
            'l1 l2 l3 l7': units() == 8 || units() == 9 
            }"></div>

        <div class="lowerClock l4 l5 l6" data-bind="css: {
            'l4 l5 l6': units() == 0 || units() == 6 || units() == 8,
            'l4': units() == 1 || units() == 4 || units() == 7 || units() == 9,
            'l5 l6': units() == 2,
            'l4 l5': units() == 3 || units() == 5
            }"></div>


    </div>

</div>

It seems like in inline css binding if condition is true then its applying the class but when checking next statement which is false it removes the class added in previous step. Is there any workaround for this inline css check because lots of switch statements are not looking good in the working code.

Shobhit Ghai
  • 101
  • 1
  • 1
  • 3
  • HI what effect are you trying to achieve? I tried your fiddle and i see a few boxes and the borders change periodically. Can you explain further or point me to working version so we can see? – Richard Banks Oct 02 '13 at 10:16
  • UPDATE: By changing the way and merging the classes in css binding its now working for me. Check out here http://jsfiddle.net/3RNKD/1/ – Shobhit Ghai Oct 02 '13 at 10:52

2 Answers2

24

I just needed this today, I prefer the multiple CSS class binding noted on the docs.

You can set multiple CSS classes at once. For example, if your view model has a property called isSevere.

<div data-bind="css: { profitWarning: currentProfit() < 0, majorHighlight: isSevere }">

You can even set multiple CSS classes based on the same condition by wrapping the names in quotes like:

<div data-bind="css: { profitWarning: currentProfit() < 0, 'major highlight': isSevere }">
kzfabi
  • 2,065
  • 1
  • 22
  • 26
15

You can use a computed function to get the CSS. Something like this:

html:

<div class="upperTensClock" data-bind="css: upperTenCSS()"></div>

Javascript:

self.upperTenCSS = ko.computed(function() {
    switch(self.tens()) {
        case 0:
            return 'l1 l2 l3';
        case 1:
            return 'l3';
        case 2:
        case 3:
            return 'l2 l3 l7';
        case 4:
            return 'l1 l3 l7';
        case 5:
        case 6:
            return 'l1 l2 l7';
        case 7:                
            return 'l2 l3';
        case 8:
        case 9:
            return 'l1 l2 l3 l7';
    }
});   
leszek.hanusz
  • 5,152
  • 2
  • 38
  • 56
  • im not sure that works as it looks like the class="upperTensClock" gets replaced. At least it did in my test – Richard Banks Oct 02 '13 at 10:20
  • 1
    it works for me, the upperTensClock is not getting replaced. If it is replaced in your case you can modify the computed function to put the upperTensClock class there. – leszek.hanusz Oct 02 '13 at 10:26
  • hmmmm weird. I did add the upperTensClock class into my code and it worked but when i set it as the attribute of the tag i got nothing which led me to believe it was being replaced. Strange one – Richard Banks Oct 02 '13 at 10:33
  • your right. I was using the attr method to set the class against the div and it was replacing. I changed to using the css bind and now it works fine. – Richard Banks Oct 02 '13 at 10:35
  • yes, actually this can be done by number of ways, but i was just trying out doing this by just inline css binding. By changing the way and merging the classes its now working for me. Check out here http://jsfiddle.net/3RNKD/1/ – Shobhit Ghai Oct 02 '13 at 10:47
  • if like me, you need to use both Fabien's way and leszek's on the same binding, here is how : `
    `
    – AXMIM Dec 08 '16 at 19:43
  • UPDATE : What I've written doesn't work. The following [question](http://stackoverflow.com/q/19256093/4625305) get more in detail for this issue. – AXMIM Dec 09 '16 at 14:58
  • thanks, both answers are good and have their uses, this is what i needed though – Andrew May 25 '17 at 15:03