John Livermore
John Livermore

Reputation: 31313

Using knockout to determine the first element in a foreach

In a knockout template binding process, I need to detect when I am processing the first element in each row as it should not have the anchor tag surrounding it.

Given the following js for knockout...

function Model() {
    var self = this;
    self.gridData = ko.observableArray('{"GridData":[["Category foo","0","0"],["Category bar","0","0"]]}');
}

var model = new Model();
ko.applyBindings(model);

and this template...

<script type="text/html" id="template">
    <table>
        <tbody data-bind="foreach: gridData">
            <tr data-bind="foreach: $data">
                <td><a href="" data-bind="text: $data"></a></td>
            </tr>
        </tbody>
    </table>
</script>

and this html...

<div data-bind="template: { name: 'template' }"></div>

Can the 'if' binding be used in some way that runs true if we are processing the 1st element?

Also, I found this SO Post, but it doesn't get me quite what I am looking for.

UPDATE:

Thanks for both answers. Using the info provided in each, I was able to find a good solution for my situation. I updated my template to the below...

<script type="text/html" id="template">
        <tbody data-bind="foreach: gridData">
            <tr data-bind="foreach: $data">
                <!-- ko if:($index()===0) -->
                <td data-bind="text: $data"></td>
                <!-- /ko -->
                <!-- ko ifnot:($index()===0) -->
                <td><a href="" data-bind="text: $data"></a></td>
                <!-- /ko -->
            </tr>
        </tbody>
</script>

Upvotes: 2

Views: 3964

Answers (2)

Francesco Pez
Francesco Pez

Reputation: 676

did you tried something like this?

<script type="text/html" id="template">
        <table>
            <tbody data-bind="foreach: gridData">
            <tr data-bind="foreach: $data">

                <td>
                    <span data-bind="text:$data,visible: ($index() === 0) " ></span>

                    <a href="" data-bind="text: $data ,visible: ($index() >=1)"></a>
                </td>
            </tr>
            </tbody>
        </table>
    </script>

The trick is the usage of "$index". I also suggest you to take a look here, you can find lots of useful special properties.

(Note also that you need to use knockout 2.x+)

[Update] Sorry to Christopher Harris, I realized he posted his answer while I was answering, all rights to him, of course

Upvotes: 1

cwharris
cwharris

Reputation: 18125

You can simply use the $index binding context, which is an observable, so you'll need to invoke it to get it's value.

JS

var vm = {
    items: ['a', 'b', 'c', 'd', 'e', 'f']
};

ko.applyBindings(vm);

HTML

<div data-bind="foreach: items">
    <div data-bind="css: { first: $index() == 0 }">
        <span data-bind="text: $index"></span>
        :
        <span data-bind="text: $data"></span>
    </div>
</div>

Fiddle: http://jsfiddle.net/xixonia/v8Eh2/

Foreach Documentation: http://knockoutjs.com/documentation/foreach-binding.html

Binding Context Documentation: http://knockoutjs.com/documentation/binding-context.html

Upvotes: 5

Related Questions