I'm looking for the best way to initialize a knockout observable array from some server data (ViewBag), and I want the array contents to be of a javascript type I have defined. Without the requirement of the JS type I could just use:
materialVarieties: ko.observableArray(@Html.Raw(Json.Encode(ViewBag.Materials)))
but I also have a material JS type that I want to use so I can have some extra ViewModel specific properties and functions i.e.:
var material = function(id, name) {
this.id = id;
this.name = name;
this.selected = ko.observable(false);
this.select = function()
{
jQuery.each(processViewModel.materials(), function(index, item)
{
item.selected(false);
});
this.selected(true);
}
}
And then the required initialization becomes:
materialVarieties: ko.observableArray([new material(1, "Apricot"), .....
Currently I build up a string from the ViewBag data and then render that as the initializer like this:
@{ var items = string.Join(",",
((IEnumerable<MaterialVariety>) ViewBag.Materials)
.Select(m => string.Format("new material({0}, {1})",
Json.Encode(m.Id), Json.Encode(m.Name)))); }
var processViewModel = {
material: ko.observableArray([@Html.Raw(items)])
But I'm wondering if there is a cleaner way than the string.Join
bit. I could wrap it up in a Helper. What do you do?
To read the observable's current value, just call the observable with no parameters. In this example, myViewModel. personName() will return 'Bob' , and myViewModel. personAge() will return 123 .
An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted. The main advantage of KO is that it updates our UI automatically when the view model changes.
I would typically serialize the array first, then map it when putting it in the view model. Would be like:
var originalVarieties = @Html.Raw(Json.Encode(ViewBag.Materials))
var processViewModel = {
materialVarieties: ko.observableArray(ko.utils.arrayMap(originalVarieties, function(variety) {
return new material(variety.id, variety.name);
}))
}
Requires a minor amount of additional processing on the client-side, but seems cleaner than building strings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With