DJ Burb
DJ Burb

Reputation: 2364

Knockout JS if condition not being recognized

I have the following knockout and HTML:

                <table>
                    <tbody data-bind="foreach: $root.selectedGroup().services">
                        <!-- ko if: ($index() % 2 === 0) -->
                        <tr>
                            <td data-bind="text:1">
                            </td>
                        <!-- /ko -->
                        <!-- ko ifnot: ($index() % 2 === 0) -->
                            <td data-bind="text: 0"></td>
                        </tr>
                        <!-- /ko -->
                        </tbody>
                    </table>

I only get the 1s, but no 0s. I have 5 items in my array

I should be displaying

1 0
1 0
1

but I only have

1
1
1

any ideas?

Upvotes: 1

Views: 342

Answers (3)

Chris Sainty
Chris Sainty

Reputation: 9306

Here is one approach

http://jsfiddle.net/L46wjw7n/

<table>
<tbody data-bind="foreach: $root.services">
        <!-- ko if: ($index() % 2 === 0) -->
        <tr>
            <!-- ko with: $root.services[$index()] -->
            <td data-bind="text:$data"></td>
            <!-- /ko -->
            <!-- ko with: $root.services[$index()+1] -->
            <td data-bind="text:$data"></td>
            <!-- /ko -->
        </tr>
        <!-- /ko -->
</tbody>

It works by looking ahead in your array for the next item and then rendering the row on each second item.

I think it would be better to model this in your viewmodel though, this is a tortured solution.

Upvotes: 1

Jamiec
Jamiec

Reputation: 136074

Knockout does appear to be doing something weird here, but to be honest this way of fudging a 2 column layout using if/ifnot bindings to conditionally render the opening and closing <tr> nodes seems a bit over-complicated.

What you could do is to rework your flat list into the appropriate rows/columns using a computed observable:

 this.services = ["bar","foo","bar","foo","bar","foo","bar","foo","bar","foo","bar","foo","bar","foo"];

this.serviceRows = ko.computed(function(){
     var result = [],
    row,
    colLength = 2;

    //loop through items and push each item to a row array that gets pushed to the final result
    for (var i = 0, j = this.services.length; i < j; i++) {
        if (i % colLength === 0) {
            if (row) {
              result.push(row);     
            }
            row = [];
        }
        row.push(this.services[i]);
    }

    //push the final row  
    if (row) {
        result.push(row);
    }

    return result;
}, this);

And then render the template in a much more straight forward manner:

<table>
    <tbody data-bind="foreach: serviceRows">
       <tr data-bind="foreach: $data">
            <td data-bind="text: ($index() % 2)"></td>
        </tr>
    </tbody>
</table>

Live example: http://jsfiddle.net/k773qf9o/

Upvotes: 0

super cool
super cool

Reputation: 6045

There is a slight issue with placement of container less if conditions

You written if/ifnot condition its like if/else so you get output either 0 or 1 for each row not both

               <table>
                    <tbody data-bind="foreach: $root.selectedGroup().services">

                        <tr>
                        <!-- ko if: ($index() % 2 === 0) -->
                            <td data-bind="text:1">
                            </td>
                        <!-- /ko -->
                        <!-- ko ifnot: ($index() % 2 === 0) -->
                            <td data-bind="text: 0"></td>
                        <!-- /ko -->
                        </tr>

                        </tbody>
                    </table>

Working fiddle here

Upvotes: 0

Related Questions