Search code examples
knockout.jsko.observablearray

Knockout: Link observable array


In a function that takes a generator, that may be a plain JS Array or an ko.observableArray, how can I use the observableArray with minimal overhead?

This is what the code currently looks like:

function (itemGenerator) { // returns observableArray or JS array
  var allItems = ko.observable();

  // triggered after user interaction
  var itemsFromGenerator = itemGenerator();
  if (ko.isObservable(itemsFromGenerator)) {
    allItems(itemsFromGenerator());

    itemsFromGenerator.subscribe(newValue => {
      allItems(newValue)
    });
  } else {
    allItems(children);
  }
}

Is there any way to replace allItems with the observableArray if itemsFromGenerator is an observableArray? So that I don't have to subscribe to further changes "manually" and have to copies of the data around.

(This is used in a TreeView implementation, where I only want to generate the items array when a node is expanded.)


Solution

  • Just have allItems contain the observable array, then you have the outside observable to track when the observable array is replaced. No subscriptions are needed.

    function (itemGenerator) { // returns observableArray or JS array
      var allItems = ko.observable();
    
      // triggered after user interaction
      var itemsFromGenerator = itemGenerator();
      if (ko.isObservable(itemsFromGenerator)) {
        allItems(itemsFromGenerator);
      } else {
        allItems(ko.observableArray(itemsFromGenerator));
      }
    }
    

    This answer is based on the information you have given. I still don't know why you need to maintain the reference to itemsFromGenerator unless it is somehow independently referenced outside of this function. I also don't know when the code under // triggered after user interaction is actually called. Finally, I don't know where/how these items in the array are used.