0

Using knockout.js I am wanting to update my View with the selected Product. My View's model is an Item that contains a list of Products in a drop down list. When the Product is changed I want the view to reflect the selected Products price and quantity.

I am passing the View's model, an Item, to my knockout ViewModel. An Item may not always have any products so how can I defensively code against this so I don't get any javascript errors with the selected product? On initial load the first product should be selected.

Lastly, if the Quantity is 0, I would like to display IN STOCK otherwise OUT OF STOCK.

Any suggestions/improvements on how to do this with knockout.js are appreciated.

Below is currently how far I've got with the code. I am having trouble showing the selected Product's quantity and price.

public class Item
{
    public IList<Product> Products { get; set; }
}

public class Product
{
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}

View.cshtml

<select data-bind="options: item.Products, value: selectedId,
                   optionsValue: 'Id', optionsText: 'Name',
                   event: { change: change }"></select>

Price: <span data-bind="text: product.Price"></span>
Quantity: <span data-bind="text: product.Quantity"></span>

var viewModel = new ItemViewModel(@Html.Raw(Json.Encode(Model)));
ko.applyBindings(viewModel);

function ItemViewModel(model)
{
    var self = this;

    self.item = model;
    self.product = ko.observable(model.Products[0]);
    alert(model.Products[0].Quantity);
    self.selectedId = ko.observable();

    self.change = function ()
    {
        self.product = ko.utils.arrayFirst(self.item.Products, function (product)
        {
            return product.Id === self.selectedId();
        });

        alert(product.Quantity);
    }
}

JSFiddle

1 Answer 1

1

I would remove the change event binding. You bind to the selected product, and that is an observable, which updates the spans - this is the work that KO does for you.

<select data-bind="options: item.Products, value: selectedProduct, 
        optionsText: 'Name'>
</select>

Price: <span data-bind="text: selectedProduct().Price"></span>
Quantity: <span data-bind="text: selectedProduct().Quantity"></span>

var viewModel = new ItemViewModel(@Html.Raw(Json.Encode(Model)));
ko.applyBindings(viewModel);

function ItemViewModel(model)
{
    var self = this;

    self.item = model;
    self.selectedProduct = ko.observable(model.Products[0]);
}

When the user picks a new product, KO automatically updates the selectedProduct object, which automatically updates the price and quantity bindings. Working JS Fiddle is here.

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

2 Comments

Added JSFiddle at bottom of question.
OK I got it working, I will update my answer. I forgot some parenthesis, always an issue with KO !

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.