I would like to understand how to call add/delete functions from within a knockout hierarchy. For example, if I am inside nested foreach, and I click on a delete button, how can I call a function that will let me delete the item (and do some other things too)?
Here's a Fiddle of the problem. https://jsfiddle.net/4a3z4urc/
In the html, the commented-out button works, but I need the function to be inside my script tags (which isn't working).
function ViewModel(data){
var self = this;
self.pages = ko.mapping.fromJS( data );
self.OutputJson = function(){
console.log(ko.toJSON(self));
}
self.removePage = function(pageName) { self.pages.remove(pageName) };
self.removeRow = function(rowType) { self.pages.pageRows.remove(rowType) };
self.removeSlide = function(slide) { self.slides.remove(slide) };
self.addSlide = function(slide) {}
}
How can I make the RemoveRow and RemoveSlide functions delete the correct item? (Json is shown below the demo). Thanks!
Your problem is that in your "inner" remove
method you don't have the information of the "currently selected" page, pageRow, slide, etc.
One solution would be to pass in the current $parent
into your click handlers:
<div data-bind="foreach: pageRows">
<section style="border:1px solid pink; padding:5px;">
<button type="submit" data-bind="click: $root.removeRow.bind($parent, $data)"
class="btn-delete"><i>×</i></button>
...
</section>
</div>
And now you can access the "currently selected" page with this
in your handler:
self.removeRow = function(rowType) { this.pageRows.remove(rowType) };
Demo JSFiddle.
Note that you also need to use $root
to access the "top level" if you inside are multiple foreach
bindings.
You can also pass in the $parent
as a paramter: root.removeRow.bind(null, $parent, $data)
, and in this case your handle would look like this:
self.removeRow = function(page, rowType) { page.pageRows.remove(rowType) };
You can read more about the different additional paramter passing options in the documentation.