Search code examples
knockout.jssubscription

Using Knockout.js how do i pass an id from a list in controller A to a button in another controller B


My page has to 2 components, called top and bottom.

The top has a button, clicking this button will take me to a different page.

The bottom controller has a list, each item on the list has an id.

Here's the issue, the button needs to get the appropriate id from the list when the list item is clicked.

Using Knockout.js how do i pass an id from a list in controller A to a button in another controller B. Can i do this via Subscription?


Solution

  • There are a few options;

    • knockout-postbox by rniemeyer has 'basic' pub/sub capabilities between models(or components), it's quite popular but maybe less straight forward for a novice.
    • you simply use a shared observable between 2 components, declared on a common parent, this is the one I snipped below:

    ko.components.register('component-button', {
      viewModel: function(params) {
        var self = this;
    
        self.sharedId = params.sharedId;
      },
      template: '<button data-bind="enable: $component.sharedId() != null, click: function () { console.log($component.sharedId()); }">' +
        '<span data-bind="visible: $component.sharedId() == null">click an item</span>' +
        '<span data-bind="visible: $component.sharedId() != null">goto item id <span data-bind="text: $component.sharedId"></span></span>' +
        '</button>',
    });
    ko.components.register('component-list', {
      viewModel: function(params) {
        var self = this;
    
        self.sharedId = params.sharedId;
        self.set = function(id) {
          if (ko.isObservable(self.sharedId)) self.sharedId(id);
        }
      },
      template: '<ul>' +
        '<li><a href="#" data-bind="click: function () { $component.set(1); }">item 1</a></li>' +
        '<li><a href="#" data-bind="click: function () { $component.set(2); }">item 2</a></li>' +
        '</ul>',
    });
    
    var viewModel = function() {
      var self = this;
      self.sharedId = ko.observable(null);
    
    };
    
    ko.applyBindings(new viewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <div>
      component button:<br />
      <component-button params="sharedId: $root.sharedId"></component-button>
    </div>
    <hr />
    <div>
      component list: <br/>
      <component-list params="sharedId: $root.sharedId"></component-list>
    </div>
    
    <script type="text/javascript">
    </script>