3

I have some trouble with knockout nested observableArrays.

My Data looks like this:

var myData = {
    Id: 123,
    Name: "string here",
    Categories: [
       {
           Id: 12,
           Name: "Category Name",
           Products: [
               {
                  Id: 1,
                  Name: 'Product1 name',
                  SomethingElse: '...'
               },
               {
                  Id: 2,
                  Name: 'Product2 name',
                  SomethingElse: '...'
               }
           ]
       },{
           // another category ...
       }
    ]
}

My ViewModel looks like this:

 viewModel = function () {
     var self = this;
     this.Id = menueItem ? ko.observable(menueItem.Id) : ko.observable(0);
     this.Name = menueItem ? ko.observable(menueItem.Name) : ko.observable();
     this.Categories = menueItem ? ko.observableArray(menueItem.Categories) : ko.observableArray([]);
     // ...
 }

So my question is, how get the Products of each Category also to an observableArray. The properties in Products not have to be observable. In my Application I have to add and remove Categories and Products.

1 Answer 1

4

Create viewmodels for categories & products. categoryViewModel should contain a function to add products and the root viewmodel should contain a function to add categories:

Root viewmodel:

viewModel = function () {
    var self = this;

    menuItem = menuItem || {
        Id: 0,
        Name: null,
        Categories: []
    };

    this.Id = ko.observable(menueItem.Id);
    this.Name = ko.observable(menueItem.Name);
    this.Categories = ko.observableArray();

    this.addCategory = function(category) {
        self.Categories.push(new categoryViewModel(category));
    }

    // create category viewmodels and add them to this root viewmodel
    for (var i = 0, l = menuItem.Categories.length; i < l; i++) {
        self.addCategory(menuItem.Categories[i]);
    }
     // ...
}

Category viewmodel:

categoryViewModel = function(categoryObj) {  
    var self = this;

    categoryObj = categoryObj || {
        Id: 0,
        Name: null,
        Products: [],
    };
    this.Id = ko.observable(categoryObj.Id);
    this.Name = ko.observable(categoryObj.Name);
    this.Products = ko.observableArray();

    this.addProduct = function(product) {
        self.Products.push(new productViewModel(product);
    }

    // create product viewmodels and add them to this category viewmodel
    for (var i = 0, l = categoryObj.Products.length; i < l; i++) {
        self.addCategory(categoryObj.Products[i]);
    }
}

Product viewmodel:

productViewModel = function(productObj) {  
    var self = this;

    productObj = productObj || {
        Id: 0,
        Name: null,
        SomethingElse: null,
    };
    this.Id = productObj.Id;
    this.Name = productObj.Name;
    this.SomethingElse = productObj.SomethingElse;
}

You will have:

viewmodel {
    Id(),
    Name(),
    Categories() : [
        categoryViewModel = {
            Id(),
            Name(),
            Products(): [
                productViewModel = {
                    Id,
                    Name,
                    SomethingElse
                }
                ...
            ]
        },
        ...
    ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Shouldn't the third to last line of the Category viewmodel be self.addProduct(...);?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.