javascript - Complemento de mapeo JS Knockout sin datos iniciales/forma vacía
knockout.js jqtouch (3)
Creo 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 generalmente termino 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 enviarlos a la vista.
EDITAR: El ejemplo es un ASP.NET MVC
Así que, básicamente, en el lado del servidor, creo un objeto de modelo de vista, que contiene todos los datos que se deben mostrar, así como todos los datos que se deben recopilar. Para un código de validación más fácil, generalmente pongo los datos que se recopilarán en su propia subclase, pero eso depende 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 estoy listo para enviar nuevamente el código, simplemente elimino una versión JS del modelo de vista.
<script type=''text/javascript''>
var dataToSendToServer = ko.toJS(viewModel);
</script>
En algunos sanarios, donde solo está cambiando una parte del modelo de vista (esto es, si está realizando actualizaciones AJAX), puede hacer algunas cosas interesantes, como cambiar plantillas para que se puedan aplicar diferentes enlaces. En este caso, estamos usando un #ID_of_Container como contenedor de la plantilla / datos originales y reemplazando la plantilla (que puede contener elementos data-bind = "") 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>
Estamos utilizando knockout y el complemento de mapeo 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.
El problema que tenemos 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.
Un par de opciones para usted además de solo administrar manualmente su modelo de vista. El complemento de mapeo admite una devolución de llamada de 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 usar un enlace que crea propiedades que faltan. Puede verse así:
//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] });
}
}
Lo usaría así (necesita pasar la propiedad como una cadena, de lo contrario, generará un error):
<input data-bind="valueWithInit: ''name''" />
Muestra aquí: http://jsfiddle.net/rniemeyer/JPYLp/
Un enfoque que estoy explorando ahora es crear un método de servicio web adicional llamado ReturnEmptyObject () que no hace 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 () se ejecuta, encuentra los observables que necesita para que no arroje un error, aunque en su mayoría estén vacíos.
De esta forma, la página puede abrirse 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.