Power Punch - Interactive Click Functionality

My question pertains to the click binding in Knockout and a specific behavior that I have observed. While there are numerous questions about click bindings on this platform, none seem to address the behavior I am encountering.

I have grasped that in Knockout, click bindings with parameters are executed during page load since Knockout needs a reference to a function. Therefore, when it encounters a function call within a binding, it executes that function expecting a returned function reference to bind to. Consequently, if I were to return another reference to a function, that particular function would be executed upon clicking the element.

So far, everything seems logical and clear.

To test this theory myself, I hastily created the following:

HTML:

<input data-bind="click: selectImportType(1)" type="button" />

JS

var functiontest = function () {
    alert('test');
};

viewModel.selectImportType = function (type) {
    viewModel.selectedImport(type);

    return functiontest;
}

Upon executing this code snippet, I noticed that the 'functiontest' reference is indeed returned to the binding, causing the functiontest function to be called as expected when the element is clicked.

However, here comes my confusion. I discovered that the selectImportType function is also invoked when the element is clicked. First, selectImportType is triggered followed by a call to the functiontest function.

How is this dual invocation possible? The reference resolved during the binding was specifically to the functiontest function!

Answer №1

When you use the following code:

data-bind="click: selectImportType(1)"

The expression selectImportType(1) is evaluated, returning your functiontest function, which is then assigned to the click binding.

Why does this happen?

This behavior is by design. When Knockout parses a binding, it creates a bindings string evaluator that acts as a dynamic function:

function createBindingsStringEvaluator(bindingsString, options) {
  var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
      functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
  return new Function("$context", "$element", functionBody);
}

In this scenario, the function body becomes:

"with($context){with($data||{}){return{'click':function(){return selectImportType(1) }}}}"

After evaluation, the parsed bindings look like this:

{
  "click": function(){return selectImportType(1)}
}

which will then be passed to the bindginHandler in the following way:

var valueAccessor = getValueAccessor(bindingKey);
                                        ||
                                       click

Therefore, the valueAccessor becomes the function:

function(){return selectImportType(1)}

Subsequently, when looking at the event binding source code ( source link here), the valueAccessor is wrapped in newValueAccessor, and upon evaluation, you get the result of executing selectImportType(1).

Finally, eventsToHandle will be your functiontest:

function () {
    alert('test');
}

This explains why the functiontest function is invoked when clicking the button.


If you're aiming for a different outcome, consider using:

data-bind="click: selectImportType.bind($data, 1)"

With this approach, the selectImportType function will only be called after clicking on the button element.

For more information on passing parameters to functions within Knockout bindings, check out these resources:

  • Passing parameters to a function in knockoutjs viewmodel

  • Passing the model as argument in the link button click using KO

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to invoke a method in Jest Enzyme without using .simulate()?

During my unit testing for a React flight seat selection application using Jest/Enzyme, I encountered a scenario where I need to test a method within my class-based component that runs after a button is clicked. However, the button in question resides deep ...

When implementing Firebase Cloud Messaging with React, the token generated by firebase.messaging().getToken() will vary with every refresh

I'm working on a React web app using Gatsby and I want to integrate push notifications through FCM. My firebase-messaging-sw.js service worker is set up, and I'm trying to retrieve a token using the following method in my app: messaging .req ...

Utilizing Ajax for dynamic PHP result determination

HTML CODE <div class="card text-center pricing-card mb-20"> <ul class="list-group list-group-flush"> <?php $gbewas = mysqli_query($con,"SELECT * FROM price"); while($okks = mysqli_fetch_array($gbewas)) { ?> <li cla ...

The ul cannot be hidden if there are no li elements within it

Currently, I am attempting to hide the unordered list (ul) on a specific page using AJAX due to certain sections of the site being Ajax-based. <ul class="sub-nav-20-m" id="filtersList_m"> </ul> Below is the code that I hav ...

Is it possible to programmatically bind a click event to each individual word in a div element?

I'm attempting to link each word within an element without altering the markup inside the element using Javascript. ...

Building Next.js with a designated maximum number of processes/threads

I've uploaded a fresh Next.js app to the cloud server using npx create-next-app. However, when I try to run the build script, the server throws an error 'pthread-create: Resource temporarily unavailable'. { "name": "next&quo ...

What should I do to resolve the message 'Ignoring invalid configuration option passed to Connection' that I received?

This is the latest message: Warning - Invalid configuration option passed to Connection: createDatabaseTable. Currently a warning, future versions of MySQL2 will throw an error for passing invalid options. The application stops responding after enco ...

Tips for extracting dynamically loaded content from a website using Node.js and Selenium?

I'm currently encountering some challenges when trying to scrape a website that utilizes react for certain parts of its content, and I'm unsure about the reason behind my inability to extract the data. Below is the HTML structure of the website: ...

Is there a method in CSS Grids to wrap the implicit grid while employing grid-auto-flow: column?

How can I achieve a layout consisting of two 4x2 grids that flow into each other, instead of being positioned side by side? Essentially, I want to split an 8x2 grid into two halves and stack them vertically. Is there a way to make the layout wrap around it ...

Dynamic calculator using JavaScript within jQuery mobile framework

I am a beginner in javascript and I am currently working on creating a mobile app using Jquery Mobile. My goal is to have the user input one value on each page, and then on the final page, display the calculated result after clicking the submit button. I ...

Interactive font-awesome icons within an interactive dropdown menu

I am currently facing an issue with using two Fontawesome icons in a clickable dropdown menu. The dropdown menu does not toggle when I click on the icons directly; however, it works when I click on the padding around them. The example provided by W3schools ...

Capture the selected hyperlink and show the corresponding page title in a designated box for reference

I want to track the links that users click on and display them in a box with an image and name of the page. Additionally, I would like to show how long the user spent on each page below the image. The images in the box should also be clickable links to the ...

Employing a PHP script to periodically replace index.html multiple times throughout the day

Imagine I have a vision of creating a basic webpage where I update a sentence daily about my emotions, replacing the old one every time. An option could be to retrieve the sentence from a database for each visitor, resulting in this page load sequence: ht ...

Error: Property 'barcodeScanner' is not readable

Currently, I am utilizing barcodescanner.js for scanning QR codes. I have successfully downloaded and linked the CaptureActivity android library to my project. However, when attempting to execute the following code: window.plugins.barcodeScanner.scan(sca ...

The initialization of the Angular service is experiencing issues

I have a service in place that checks user authentication to determine whether to redirect them to the login page or the logged-in area. services.js: var servicesModule = angular.module('servicesModule', []); servicesModule.service('login ...

What is the best way to initiate a class constructor with certain parameters left out?

Currently, I am facing a challenge while trying to pass various combinations of arguments to a class constructor. The constructor has 2 optional arguments. Here is the code snippet: class MyClass { foo(a, b) { return new MyClass(a, b); } bar( ...

Angular allows developers to easily show or hide different elements on a webpage

I have a situation where I need to display date and time within two separate div elements. There are two checkboxes available: 1. Add Additional: This will add one more div for each date and time. 2. Time/Date will be the same: This will add just the date ...

The Final Div Fluttering in the Midst of a jQuery Hover Effect

Check out my code snippet here: http://jsfiddle.net/ZspZT/ The issue I'm facing is that the fourth div block in my example is flickering quite noticeably, especially when hovering over it. The problem also occurs occasionally with the other divs. Ap ...

Struggling to find a solution for your operating system issue?

We are currently attempting to utilize the markdown-yaml-metadata-parser package for our project. You can find more information about the package here. Within the package, it imports 'os' using the following syntax: const os = require('os ...

Firefox failing to trigger key events within iframe

For fun, I created my own little JSFiddle website where I built a Snake implementation that works great in Chrome. However, when I try to use it in Firefox, I can't control the player with the arrow keys or WASD. You can check it out here: I read on ...