Calling a function in a parent's scope in nested view model

3,133 views
Skip to first unread message

Brian Vallelunga

unread,
Oct 28, 2011, 1:54:48 PM10/28/11
to knock...@googlegroups.com
I have a view model that looks like this:

var row = function(name) {
   this.name = name;
}

var set = function() {
   this.rows = ko.observableArray([new row('row 1')]);
   this.deleteRow = function(item) { this.rows.remove(item); };
}

var viewModel = {
   this.sets: ko.observableArray([new set(), new set()]);
}

I then have templates using the jQuery templating library that display the sets with their nested rows. What I want is to have the the deleteRow function be called from an item rendered by the nested row template. I can't figure out how to get this scoped properly. If I simply do: <button data-bind="click: deleteRow($data)">Delete</button> it's going to look for a "deleteRow" function on the row object itself, which doesn't exist. I need to tell it to use its parent set as the scope to look in. Any thoughts on how to do this?



Joe McBride

unread,
Oct 28, 2011, 7:19:36 PM10/28/11
to knock...@googlegroups.com
I've used a bindingHandler to solve this in the past.  Here's an example fiddle.


Note that this works with 1.2.1, though may have issues with the lastest beta.

rpn

unread,
Oct 28, 2011, 9:51:51 PM10/28/11
to knock...@googlegroups.com
In 1.3 beta this is really easy.  1.3 exposes the variables $data, $parent, $parents, and $root.  $parent would give you one scope level up, so you can call $parent.deleteRow.

Prior to 1.3, I would typically use the templateOptions functionality to pass the method down into the child template.  In general it would look like:

<div data-bind="template: { name: 'rowTmpl', foreach: rows, templateOptions: { delete: deleteRow } }"></div>

then inside of 'rowTmpl', you would access the method using $item.delete

In this case, you will want to take care that "this" is what you expect when deleteRow is called.  There are several ways to do this, but an easy one is to bind it to the current this in your constructor:

this.deleteRow = function(item) { this.rows.remove(item); }.bind(this);

Brian Vallelunga

unread,
Oct 29, 2011, 7:39:52 PM10/29/11
to knock...@googlegroups.com
Thanks, $parent is working out very well.

mcoolin

unread,
Nov 29, 2011, 10:32:31 AM11/29/11
to knock...@googlegroups.com
Hi rpn,

Would you happen to have this in a fiddle somewhere, trying to get something like this working now.

Thanks

rpn

unread,
Nov 29, 2011, 11:14:30 AM11/29/11
to knock...@googlegroups.com
Hello-
Here is a basic one: http://jsfiddle.net/rniemeyer/hYTDx/ .  If you have something specific in mind, let me know and I can try to help out.
Reply all
Reply to author
Forward
0 new messages