1

SuperNoob here, trying to load varying multiple "Options" either as a string[] or object, to a "Product" that can be added to a shopping cart using Knockout: (working from John Papa's PluralSight Knockout Change Tracking example) Here is the view:

<div>
    <span>OptionsArray: </span>
    <ul data-bind="foreach: optionsArray">
        <li data-bind="text: $data"></li>
    </ul>
</div>

Here is the JSON converted into C#:

{Id = 4, ModelId = 1, SalePrice = 1.00, ListPrice = 1.00, Rating = 5, Photo = "smallCoffee.jpg", CategoryId = 1, ItemNumber = "smallCoffee", Description = "Small Coffee", Model = new Model(){ Name = "Small Coffee", Brand = "Tim Hortons", Id = 1 }, Category = drinkCat, Options = new Options(){Name = "Sugar"}, OptionsArray = new string[]{"Sugar", "Cream"}}

This javascript function works, loading json into an "products" array of Products, except I can't get it to iterate through varying multiple options for each product. Here is the function part of the view model:

loadProductsCallback = function (json) {
            my.vm.tracker().markCurrentStateAsClean();
            $.each(json, function (i, p) {
                products.push(new my.Product(selectedProduct)                            
                        .id(p.Id)
                        .salePrice(p.SalePrice)
                        .photo(p.Photo)
                        .category(new my.Category()
                        .id(p.Category.Id)
                        .name(p.Category.Name)
                            )
                        .model(new my.Model()
                        .id(p.Model.Id)
                        .name(p.Model.Name)
                        .brand(p.Model.Brand)
                            )
                        .options(new my.Options()
                        .name(p.Options.Name)
                            )                            
                        .description(p.Description)
                        .rating(p.Rating)
                        .stateHasChanged(false);
                        $.each(p.OptionsArray, function(i, o) { p.optionsArray.push(o);});
                );
            });

And here is the Product object that is taking all the data:

Product = function (selectedItem) {
    var self = this;
    self.id = ko.observable();
    self.salePrice = ko.observable();
    self.photo = ko.observable();
    self.model = ko.observable();
    self.options = ko.observable();
    self.optionsArray = ko.observableArray(["1", "2"]);
    self.category = ko.observable();
    self.description = ko.observable();
    self.rating = ko.observable();
    self.isSelected = ko.computed(function () {
        return selectedItem() === self;
    });
    self.isDrink = ko.computed(function () {
        return this.category() ? this.category().id() === 1 : false;
    }, self),
    self.isFood = ko.computed(function () {
        return this.category() ? this.category().id() === 4 : false;
    }, self),

    self.shortDesc = ko.computed(function () {
        return this.model() ? this.model().name() : "";
    }, self),
    self.opt = ko.computed(function () {
        return this.options() ? this.options().name() : "";
    }, self),
    self.optQty = ko.computed(function () {
        return this.options() ? this.options().qty() : "";
    }, self),
    self.photoUrl = ko.computed(function () {
        return photoPath + this.photo();
    }, self),
    self.rating.subscribe(function () {
        this.stateHasChanged(true);
    }, self),
    self.stateHasChanged = ko.observable(false);
};

The loadProductsCallback function works fine except for the part adding the nested OptionsArray in. I've tried a nested $.each functions and just simply .optionsArray(p.OptionsArray).

There is a lot more code: I hope that this is enough to make sense.

Dear Stackers, how can I properly load the OptionsArray into the Products object using this function?

3
  • How are you doing the chaining on your observable properties? Also there seems to be some errant brackets. Have you looked into using the mapping plugin to do this for you? Commented Jun 13, 2012 at 19:29
  • I'm not sure about the chaining could you expand a bit more please? It's possible the brackets may not match up since I cut and paste this out I will check that again. The mapping plugin looks very handy however since everything else is working right now with this, I'm trying to understand how this model works before moving on. I feel like if I could figure out how to load this array, then I will understand KO better. Commented Jun 13, 2012 at 23:48
  • I was just querying the mapping of your Product properties. new my.Product(selectedProduct).id(p.Id).salePrice(p.SalePrice) since the id property would have to return the product in order to be able to then chain the setting of the salePrice property. Commented Jun 14, 2012 at 0:37

1 Answer 1

1

Not sure I'm quite understanding your code but here goes.

You are new'ing up a product then trying to loop through a collection and map it to options. Except you are pushing the results to the source object.

What about this.

loadProductsCallback = function (json) {
    my.vm.tracker().markCurrentStateAsClean();
    $.each(json, function (i, p) {
        var newProduct = new my.Product(selectedProduct)                            
                .id(p.Id)
                .salePrice(p.SalePrice)
                .photo(p.Photo)
                .category(new my.Category()
                .id(p.Category.Id)
                .name(p.Category.Name)
                    )
                .model(new my.Model()
                .id(p.Model.Id)
                .name(p.Model.Name)
                .brand(p.Model.Brand)
                    )
                .options(new my.Options()
                .name(p.Options.Name)
                    )                            
                .description(p.Description)
                .rating(p.Rating)
                .stateHasChanged(false);
        $.each(p.OptionsArray, function(i, o) { 
            newProduct.optionsArray.push(o);
        });

        products.push(newProduct);
    });
}

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, the way you created a var and made 2 $.each calls worked! Plus, the OptionsArray was coming up undefined in the javascript console, so I changed the Product definition and the JSON to: 'new Product(){Id = 4, ModelId = 1, SalePrice = 1.00, ListPrice = 1.00, Rating = 5, Photo = "smallCoffee.jpg", CategoryId = 1, ItemNumber = "smallCoffee", Description = "Small Coffee", Model = new Model(){ Name = "Small Coffee", Brand = "Tim Hortons", Id = 1 }, Category = drinkCat, OptionsArray = new List<Options>(){new Options(){Name="Cream"}, new Options(){Name="Sugar"}}}'
Sorry not enough rep to upvote your solution, but I promise to come back and do so after 2 points.

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.