2011-07-18 11 views
18

Estamos utilizando el complemento de mapeo knockout y el knockout para facilitar el enlace de datos en nuestra aplicación web jQTouch. La razón por la que usamos el plugin de mapeo es poder usar knockout sin la necesidad de definir/cambiar viewmodels manualmente en javascript. El complemento de mapeo funciona muy bien cuando tiene una carga inicial de datos de la base de datos del lado del servidor/cliente.Complemento de mapeo JS knockout sin datos iniciales/forma vacía

El problema que estamos teniendo es que tenemos algunas pantallas/vistas que tienen una forma en la que es posible que no haya datos iniciales. Sin estos datos iniciales, el complemento de mapeo no puede 'generar' el modelo de vista (ko.mapping.fromJS). Esto significa que todavía tenemos que definir nuestros modelos de vista a mano para partes grandes de nuestras vistas.

¿Me equivoco al asumir que este es un escenario que admite el complemento de mapeo (debería)? Quiero decir, esto significa que el plugin de mapeo solo se puede usar en escenarios en los que siempre tienes una carga de datos inicial.

Respuesta

19

Un par de opciones para usted además de solo administrar manualmente su modelo de vista. El complemento de asignación admite una devolución de llamada create que le permite personalizar cómo se crea. Esto se puede usar para agregar propiedades predeterminadas a un objeto, si faltan.

Algo como esto: http://jsfiddle.net/rniemeyer/WQGVC/

Otra alternativa es utilizar una unión que crea propiedades que faltan. Podría verse como:

//create an observable if it does not exist and populate it with the input's value 
ko.bindingHandlers.valueWithInit = { 
    init: function(element, valueAccessor, allBindingsAccessor, data) { 
     var property = valueAccessor(), 
      value = element.value; 

     //create the observable, if it doesn't exist 
     if (!ko.isWriteableObservable(data[property])) { 
      data[property] = ko.observable(); 
     } 

     //populate the observable with the element's value (could be optional) 
     data[property](value); 

     ko.applyBindingsToNode(element, { value: data[property] }); 
    } 
} 

Se podría utilizar de esta manera (necesidad de transferir la propiedad como una cadena, de lo contrario será error):

<input data-bind="valueWithInit: 'name'" /> 

Muestra aquí: http://jsfiddle.net/rniemeyer/JPYLp/

+0

Gracias RP Niemeyer, voy a probar esto en los próximos días. ¡Suena prometedor! – MichaelvR

+0

El enlace personalizado funciona perfectamente, ¡gracias! – MichaelvR

+1

el enlace de cust init funcionó muy bien para mí, pero no me gustó la actualización dinámica del atributo de enlace de datos en el enlace, así que sugiero usar [elementos de virual] (http://knockoutjs.com/documentation/custom-bindings -for-virtual-elements.html). \t \t Algo así como: <- ko valueWithInit: 'propC' ->

4

I piense que la solución a su problema proviene de pensar en el modelo de vista de la manera incorrecta. Un modelo de vista no solo es algo que entrega datos a la vista, sino también un marcador de posición para volver a enviar los datos.

La forma en que suelo terminar trabajando con knockout, nunca termino enviando un modelo de vista vacía a la vista. El modelo de vista generalmente tiene todos los campos a los que me estoy vinculando. Si bien pueden ser cadenas vacías, o objetos inicializados sin valores de visualización, los objetos reales salen aún, con una representación adecuada de cada objeto en los campos a los que me estoy vinculando.

Es posible que desee considerar simplemente enviar objetos vacíos en lugar de nada a la vista.

EDIT: El ejemplo es la ONU ASP.NET MVC

Así basiclaly, i en el lado del servidor, i crear un objeto vista del modelo, que contiene todos los datos que hay que mostrar, así como todos los datos eso necesita ser recolectado Para obtener un código de validación más sencillo, generalmente pongo los datos que se recopilarán en su propia subclase, pero esa es una cuestión de las necesidades de su código.

En cualquier caso, cualquier objeto que vaya a la vista se ejecuta desde una clase vmBase que básicamente proporciona un método toJSON() que genera la serialización JSON del objeto. Esto se llama en mi opinión por el motor de vista. Como se muestra en el código a continuación.

 <script type='text/javascript'>   
     var viewModel = ko.mapping.fromJS(<%= Model.ToJson() %>);      

     $(document).ready(function() {   
      ko.applyBindings(viewModel);        
     });     
    </script> 

cuando esté listo para enviar el código de copia de seguridad, simplemente se quita tirar una versión JS del modelo de vista.

<script type='text/javascript'> 
    var dataToSendToServer = ko.toJS(viewModel); 
</script> 

En algunos sanarios, donde sólo una parte del modelo de visión está cambiando (esto es si usted está haciendo cambios AJAX), usted puede hacer algunas cosas interesantes como, plantillas de conmutación de modo tan diferente de unión puede ser applyed. En este caso estamos usando un #ID_of_Container como contenedor de los datos originales/plantilla y la sustitución de la plantilla (que puede contener datos-bind = "" elementos) una nueva plantilla ID_of_Template

<script type='text/javascript'> 
    ko.cleanNode($("#ID_of_Container")); 
    delete (viewModel.Some_Element_To_Be_Updated); 
    viewModel = ko.mapping.updateFromJS(viewModel, New_Data_For_That_Element); 

    // Use ko.toJS(viewModel) because standard template plugin doesn't understand 
    // knockout observables 
    $("#ID_of_Container").html($("#ID_of_Template").tmpl(ko.toJS(viewModel))) 
    ko.applyBindings(viewModel, $("#ID_of_Container")[0]); 

</script> 
+0

¿También está utilizando el complemento de mapeo KO? Eso le permite generar el modelo de vista, en lugar de tener que definirlo 'a mano'. Esta es la parte con la que estamos teniendo problemas. – MichaelvR

+0

Espero que la edición ayude. Me tomó un poco darme cuenta de que puedo hacer este tipo de cosas con knockout. BUt termina con resultados bastante buenos. Realmente le da al sitio web un cliente grueso y un flujo AJAX muy suave. –

0

Un enfoque Estoy explorando ahora es crear un método de servicio web adicional llamado ReturnEmptyObject() que no hace nada más que crear y devolver un objeto recién instanciado (cuyas propiedades serían valores predeterminados) en el lado del servidor. El objeto (en mi caso C#) se serializa a JSON, y finalmente llega a la llamada jQuery Ajax .... y luego pasa a ko.mapping.updateFromJS() ... que crea los observables necesarios en la carga de la página inicial. antes de llamar a ko.applyBindings().

Cuando ko.applyBindings() ejecuta, encuentra los observables que necesita para que no se emite un error, a pesar de que son prácticamente vacío.

De esta manera, la página se puede abrir inicialmente sin rellenar ninguno de los campos. Sin embargo, si agrego algunas propiedades nuevas a mi clase en el lado del servidor, aparecen automáticamente en el lado del cliente.

Cuestiones relacionadas