8

Knockout - Click Connect to Object Function - Scope Issues

 3 years ago
source link: https://www.codesd.com/item/knockout-click-connect-to-object-function-scope-issues.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Knockout - Click Connect to Object Function - Scope Issues

advertisements

I have a simple collection of strings that I want to use Knockout's foreach binding to create buttons for. The button uses click binding to load some data in my object. The bindings happen correctly, but the actual load function fails, telling me that a method isn't supported.

Here's what I have:

//My Object
function MyObject()
{
    this.WorkerFunction = function(id)
    {
        //Do Work
    }

    this.Load = function(id)
    {
        //Call Another Function
        this.WorkerFunction(id); //Error: Object doesn't support property or method 'WokerFunction'
    }
}

//Creation
var myObject = new MyObject();

//VM Binding
var vm = ko.mapping.fromJS(jQueryAjaxObject);
ko.applyBindings(vm);

//HTML
<div data-bind="foreach: stringIDCollection">
    <button data-bind="click: function() { myObject.Load($data) }"> Load </button>
</div>


When a button is clicked, I get the following error: Object doesn't support property or method 'WokerFunction'. I had a similar error with a mouse move event elsewhere in my code, but I was able to solve that using the bind function like below. However, I am unable to get this to work for the Knockout binding.

$("myElement").mousemove(this.MouseMove.bind(this));


Edit

I have also tried var self = this; and self.WorkerFunction(id);, but I got the same results; the method isn't supported.


Q: What is the correct way to handle a Knockout Click Binding to an object's function while maintain the this scope?


You must store a reference to this.

Read about how the this keyword works in JavaScript.

// converted to commonly accepted coding style
function ViewModel() {
    var self = this;

    this.workerFunction = function(id) {
        //Do Work
    };

    self.load = function(id) {
        self.workerFunction(id);
    };

    // do initialization here...
    self.stringIDCollection = ko.mapping.fromJS(/*...*/);
}

ko.applyBindings(new ViewModel());


Apart from that: Don't use JavaScript code in bindings. (Especially not entire functions. Not ever.) That's exactly the thing knockout has been designed to avoid.

Make load a method of your view model, like shown above

<div data-bind="foreach: stringIDCollection">
    <button data-bind="click: $root.load">Load</button>
</div>


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK