Peter Kirby
Peter Kirby

Reputation: 1985

How to specify different click bindings in a foreach loop with KnockoutJS

I have a knockout observable array of the form:

this.controls = ko.observableArray([
        { 
            name: 'Previous',
            action: '$root.previous'
        },
        { 
            name: 'Next'          ,     
            action: '$root.next'
        },
        { 
            name: 'Save',
            action: '$root.save'
        }
]);

I would like to do the following in my view:

<div class="controls navigation">
    <ul data-bind="foreach: $root.controls">
        <li>
            <span data-bind="text: name, click: action"></span>
        </li>
    </ul>
</div>

The view creates three separate span which are essentially buttons. My goal is have the corresponding action in the viewmodel to be called each time a user clicks on a specific span.

However, this does not work.

How might I go about looping through an array and specifying different click binding actions for each item?

I could easily just write out each span individual (in this specific case, since there is only 3 items in the array), but I am curious how I could accomplish this using the array.

Upvotes: 1

Views: 142

Answers (2)

CodeThug
CodeThug

Reputation: 3192

You are very close. Assuming you have previous, next, and save defined like this

this.previous = function() { ... };

And assuming you define self like this

self = this;

Then all you have to do is update your array like this:

this.controls = ko.observableArray([
    { 
        name: 'Previous',
        action: self.previous
    },
    { 
        name: 'Next',     
        action: self.next
    },
    { 
        name: 'Save',
        action: self.save
    }
]);

Please note how action is no longer a string, but rather a reference to a function.

http://jsfiddle.net/tlarson/Dwwft/

Upvotes: 3

politus
politus

Reputation: 6086

Perhaps you can refactor this like so

this.controls = ko.observableArray([
        { 
            name: 'Previous'
        },
        { 
            name: 'Next'     
        },
        { 
            name: 'Save'
        }
]);
this.myAction = function (value, event) {
    if(value == 'Previous')
    {
       // do stuff
    }
    else if(value == 'Next')
    {
       // do stuff
    }
    else if(value == 'Save')
    {
       // do stuff
    }
    return true;
}

then

<div class="controls navigation">
    <ul data-bind="foreach: $root.controls">
        <li>
            <span data-bind="text: name, click: myAction"></span>
        </li>
    </ul>
</div>

Upvotes: 0

Related Questions