0
votes

I have a view model that contains 2 related (master / detail) arrays that I want to bind to.

  var ViewModel = function (data) {
        var self = this;
        self.CategoryList = ko.observableArray(data.CategoryList);
        self.ItemList = ko.observableArray(data.ItemList);
   }

Where Category is an array of { categoryID: 1, name: "Red Items" } etc

and Item is an array of { itemID: 1, categoryID: 1, name: "Red Widget" } etc

I have a handful of categories and possibly several hundred items. I am struggling with how to represent these in my view model in a way that I can enumerate categories and get to associated items or across all items and get to categories.

It doesn't seem efficient to maintain duplicate information on both lists and I don't want to be sending more data than needed over the wire.

One approach: create Item and Category objects and modify the prototype to include filtering (ko.computed) functions. category.Items() or item.Category().Name but I am not 100% how to best accomplish this within knockout.js given my need to load and save data.

I am not wed to arrays of simple JSON objects. Assuming I go the function / prototype route, how do I load and save my arrays of objects?

1

1 Answers

0
votes

I think that you require a better data structure than an array, since -as you said- it's not optimal to keep duplicate information. Instead of having an array listing your categories, why don't use a hash table, or as we simply know in javascript, an object?

{
    1: "Red Items",
    2: "Blue Items",
    3: "Green Items",
    4: "Yellow Items",
}

(You can use a simple method to create the hash from the array)

var createHashFromArray = function(arr) {
  var hash = {}
  for (var i = 0, var len = arr.length; i < len; i++)
    hash[i] = arr[i];
  return hash;
}

From there, you can bind your viewModel according to the categories you need. You can even set up them as dynamic arrays using ko.computed in order to organize them in your view.

<div data-bind="foreach: redItemsOnly">
  <span data-bind="text: itemId">ID</span>
  <span data-bind="text: name">NAME</span>
</div>

And in your javascript...

self.redItemsOnly = ko.computed(function() {
return ko.utils.arrayFilter(self.ItemList(), function(item) 
{
    return self.CategoryHash[item.categoryID] === "Red Items"
});
}, self)

I'm not sure if this is what you want, but I hope this approach helps you to find other ways to come up with what you need.