Search code examples
knockout.jsknockout-components

functions in knockout components (knockoutjs 3.2+)


I'm trying to understand knockout 3.2 components, but i'm stuck.

I have a component "Customers"

ko.components.register("customers", {
  viewModel: function (params) {
    var self = this;
    this.customers = ko.observableArray();
    this.selectedCustomerId = ko.observable(1);
    this.selectCustomer = function (data) {
        selectedCustomerId(data.Id);
    };

    $.getJSON('http://localhost:49435/Customer/GetCustomers', this.customers);
},
template: "<div><table class=\"table table-condensed table-responsive\"><thead><tr><th>Customer ID</th><th>Name</th><th>City</th></tr></thead><tbody data-bind=\"foreach: customers\"><tr><td data-bind=\"text: Id\"></td><td data-bind=\"text: Name, click: $root.selectCustomer\"></td><td data-bind=\"text: City\"></td></tr></tbody></table></div>"
});

But when binding, I get the following Error:

Unable to process binding "click: function (){return $root.selectCustomer }" Message: Cannot read property 'selectCustomer' of undefined

Next thing I want to do is communicating the selectedCustomerId to another component. Is this possible using the PubSub Synchronization and how is this possible. Can someone give me a hint where to start.


Solution

  • Use $parent instead of $root in you bindings. $root generally refers to view model which is passed to ko.applyBindings method.

    Also you have another error in your code - in selectCustomer method you are trying to access global variable selectedCustomerId which does not exist. You should prefix it with self to be able to access local variable which is created in your view model.

    var self = this;
        self.customers = ko.observableArray();
        self.selectedCustomerId = params.SelectedCustomer;
        self.selectCustomer = function (data) {
            self.selectedCustomerId(data.Id);
        };
    

    Regarding passing selectedCustomerId to another component - you can create observable in your root view model (which you pass to ko.applyBindings) and then pass it to your components like this:

    <customers params='SelectedCustomer:selectedCustomer'></customers>
    

    And then use this observable when data binding. Check this fiddle for the working example.