title: Knockout.js - Pub/Sub between components, two-way conversation
body: <p>my Knockout app is made of different components representing the different part of a form - so I have a "languages" component, a "countries" component, a "tags" component and so on. In each of these components I have an observable array to which I subscribe and send notifications through ko.postbox.notifySubscribers anytime these observables change. In another component, called filters, which serves as a collector of all the filters selected by the user in the form, I receive the changes in these observables through ko.postbox.subscribe.</p>
  
  <p>My question is: what if I want to make changes in the filters component and having them reflected in the other components too? That is, how can I transform this one-way conversation in a two-way conversation? </p>
  
  <p>For example, in the languages component I have a dropdown menu and user selects languages. In the filters menu I have the list with the selected languages (checkboxes), and I would like the user to be able to deselect items from here while still updating the dropdown in the main component.  </p>
  
  <p>Posting code for languages component and filters component,
  Thanks</p>
  
  <p><strong>Languages.js</strong></p>
  
  <pre><code>ko.components.register("languages",{ 
   viewModel: function(){
    var self            = this;
    self.languages      = ko.observableArray();
    self.selectedLangs  = ko.observableArray();
  
    xhr.languages()
     .done(function (langs) {
       self.languages(langs);
    }); 
  
    self.selectedLangs.subscribe(function(values) {
      ko.postbox.notifySubscribers(
       _.map(values,function(val){
        var obj = _.findWhere(self.languages(), {id: val});
        return obj.text;
      }), "selectedLangs");
    });
  },
  template: 
  '&lt;fieldset id="language" class="wfp-u-1"&gt;\
    &lt;div class="wfp-grid"&gt;\
      &lt;label for="dss-language" class="wfp-u-1 wfp-u-lg-1-4"&gt;\
        Language &lt;span class="loader"&gt;&lt;i class="icon-loader"&gt;&lt;/i&gt;&lt;/span&gt;\
        &lt;em&gt;Multiselection available&lt;/em&gt;\
      &lt;/label&gt;\
      &lt;select id="dss-language" name="language" multiple="" class="wfp-u-1 wfp-u-lg-3-4 ui dropdown search selection"\
        data-bind="\
          options: languages,\
          optionsText: \'text\',\
          optionsValue: \'id\',\
          optionsCaption: \'Select one or more languages\',\
          selectedOptions: selectedLangs\"&gt;\
      &lt;/select&gt;\
    &lt;/div&gt;\
  &lt;/fieldset&gt;'
  });
  </code></pre>
  
  <p><strong>Filters.js</strong></p>
  
  <pre><code>ko.components.register("filters",{ 
   viewModel: function(){
  
  var self = this;
  self.selectedLangs      = ko.observableArray();
  
  ko.postbox.subscribe(function(langs) {     
    self.selectedLangs(langs);
  }, self, "selectedLangs");
  },
  template: 
  '&lt;ul class="wfpList wfpFieldList mCustomScrollbar"&gt;\
    &lt;li&gt;\
      &lt;a data-target="language"&gt;Language&lt;/a&gt;&lt;i class="ico-angle-down"&gt;&lt;/i&gt;\
      &lt;!-- ko foreach: selectedLangs --&gt;\
        &lt;span data-bind="text: $data"&gt;&lt;/span&gt;\
      &lt;!-- /ko --&gt;\
    &lt;/li&gt;\
  &lt;/ul&gt;'
  });
  </code></pre>