2011-08-13 7 views
8

Estoy buscando la mejor manera de inicializar una matriz observable de algunos datos del servidor (ViewBag), y quiero que los contenidos de la matriz sean de un tipo javascript I ha definido. Sin el requisito del tipo JS tan sólo pudiera utilizar:Knockout JS inicializando una matriz observable de datos del servidor usando un tipo de Javascript

materialVarieties: ko.observableArray(@Html.Raw(Json.Encode(ViewBag.Materials))) 

pero también tengo un tipo de material JS que quiero usar para que pueda tener algunas propiedades específicas ViewModel extra y funciones, es decir:

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); 
     } 
} 

y entonces la inicialización necesaria se convierte en:

materialVarieties: ko.observableArray([new material(1, "Apricot"), ..... 

Actualmente construyo una cadena partir de los datos ViewBag y después de un procesamiento que como el inicializador de la siguiente manera:

@{ 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)]) 

pero me pregunto si hay una manera más limpia que el bit string.Join. Podría envolverlo en un Ayudante. ¿Qué haces?

+1

¿Por qué no crear un método de extensión HtmlHelper? Tome un argumento genérico y devuelva la salida codificada. – Anuj

+0

@Anuj Sí, eso es lo que estaba pensando ("Podría envolverlo en un Helper"), también tendría que tener una cadena que representara el tipo JS. El problema surge al calcular las propiedades para usar en el constructor JS (y la orden requerida). Puedo reflejar el argumento genérico para obtener las propiedades, pero esperaba usar mis Modelos del lado del servidor (no quiero otro conjunto de VM del lado del servidor) y tienen otras propiedades que no necesito en mi JS. Y eso todavía me deja el problema del orden del constructor ... ¿a menos que me falta algo? –

Respuesta

15

Normalmente serializaría la matriz primero, luego la correlacionaría al ponerla en el modelo de vista. Sería como:

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); 
    })) 
} 

Requiere una cantidad menor de un procesamiento adicional en el lado del cliente, pero parece más limpio que la construcción de cadenas.

+0

ah, eso se ve bien. Soy nuevo en Knockout y no estaba al tanto de utils.arrayMap. Gracias. –

+0

podría simplemente usar el mapa de jQuery, supongo ... –

+2

sí, no hay nada de especial en ko.utils.arrayMap. Código bastante simple. El mapa jQuery haría lo mismo. –

Cuestiones relacionadas