Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout JS initializing observable array from server data using a javascript type

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?

like image 941
Simon Fox Avatar asked Aug 13 '11 01:08

Simon Fox


People also ask

How do you get the knockout value from observable?

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 .

What is Ko observable ()?

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.


1 Answers

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.

like image 185
RP Niemeyer Avatar answered Oct 05 '22 15:10

RP Niemeyer