Search code examples
javascriptjqueryforeachknockout.jsknockout-2.0

Knockout JS foreach as input of function


Is there a way to use the data in a foreach as the input of a separate function? Instead of using the source for an image, I instead want to leave it blank and call a function on error which will allow me to manipulate the SVGs. My images are currently in the format:

<img src='' onerror=myFunction(imgUrl)></img>

However I would like to be able to do something like this:

<div data-bind='foreach: arrayValue'>
    <div>
      <p data-bind='text: $data.name'></p>
      <img src='' data-bind='onerror: myFunction($data.img)'></img>
    </div>
</div>

JS

function myFunction(img){
    do something...
}

var myObjArr = [
    {name: 'entry 1', img: imageUrl}, {name:'entry 2', img: image2Url},...
]

var model = function() {
    this.self = this;
    this.arrayValue = ko.observable(myObjArr);
}
ko.applyBindings(new model());

Solution

  • Yes, the event binding exists for that. When in a foreach loop, KO will automatically pass the current item as a parameter to the function. Note that you have to use $parent when referring to the function on your viewmodel from inside the loop, because of the way KO handles the binding context.

    <div data-bind='foreach: item'>
        <div>
          <p data-bind='text: $data.name'></p>
          <img src='' data-bind='event: { error: $parent.errorHandler }'></img>
        </div>
    </div>
    

    JS:

    var model = function() {
        var self = this;
        self.item = ko.observableArray([
            {name: 'entry 1', img: imageUrl}, {name:'entry 2', img: image2Url},...
        ]);
        self.errorHandler = function(item) {
            // 'item' will be an object from the self.item array
            // So you can use item.img, item.name, etc.
        }
    }