Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call standard Knockout click binding from a custom binding

I would like to create a 'conditional click' binding in KnockoutJS. Basically this is a standard click binding like you would use it in Knockout, but a condition needs to be met in order for the attached function to be executed. In my case, the best option is to create a custom bindinghandler in which you then call the standard click binding if allowed.

ko.bindingHandlers.safeClick = {
    'init': function(element, valueAccessor, allBindingsAccessor, context) {
        $(element).click(function() {
            if(mycondition == true) {
                // call the standard click binding here -> this is the part I don't know
            }
        });
    }
}

I want to replace all of my standard click bindings with this custom binding. Therefore it is important to call the click binding in the right way, so all of the parameters provided in HTML are passed through to the function. For example:

<a href="#" data-bind="click: basevm.gotopage.bind($data, '#homepage')">Home</a>
<a href="#" data-bind="click: itemvm.activateItem">Activate</a>

These need to be replaced by

<a href="#" data-bind="safeClick: basevm.gotopage.bind($data, '#homepage')">Home</a>
<a href="#" data-bind="safeClick: itemvm.activateItem">Activate</a>

I would very much appreciate it if you could help me with the missing part in the custom binding.

like image 649
Bram W. Avatar asked Aug 09 '13 08:08

Bram W.


People also ask

What are Knockout bindings?

Knockout's declarative binding system provides a concise and powerful way to link data to the UI. It's generally easy and obvious to bind to simple data properties or to use a single binding. For more complex bindings, it helps to better understand the behavior and syntax of Knockout's binding system.

What is $parent in Knockout?

$parent : This is the view model object in the parent context, the one immeditely outside the current context. $root : This is the main view model object in the root context, i.e., the topmost parent context. It's usually the object that was passed to ko.

How do you activate Knockout?

To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.


1 Answers

The correct way to delegate the click biding here is the following:

  • you take your original function (e.g using valueAccessor())
  • create a new valueaccessor function where you return a new function containing your condition which then calls your original function. And pass this new valueaccessor to the click binding.

So your safeClick will look like this:

ko.bindingHandlers.safeClick = {
    'init': function (element, valueAccessor, allBindingsAccessor, 
                      viewModel, bindingContext) {
        var originalFunction = valueAccessor();
        var newValueAccesssor = function() {
            return function () {
                if (mycondition == true)
                    //pass through the arguments
                    originalFunction.apply(viewModel, arguments);
            }
        }
        ko.bindingHandlers.click.init(element, newValueAccesssor, 
            allBindingsAccessor, viewModel, bindingContext);
    }
}

Demo JSFiddle.

This is will work for the first click, and you don't have to manually subscribe on the click event or trigger it with jQuery.

like image 165
nemesv Avatar answered Sep 26 '22 03:09

nemesv