Knockoutjs, actualización de ViewModel después de la llamada de Ajax
-
13-10-2019 - |
Pregunta
Estoy usando Knockout y el complemento de mapeo Knockout.
- Mi acción MVC3 devuelve una vista y no JSON directamente como tal, convierto mi modelo en JSON.
- Este es un formulario de inscripción de datos y, debido a la naturaleza de la validación del sistema, se realiza todo en la capa de servicio, con advertencias devueltas en un objeto de respuesta dentro del Modelo View.
- Los enlaces y actualizaciones iniciales funcionan correctamente es el comportamiento de "post-actualización" que me está causando un problema.
Mi problema es después de llamar a la publicación de Ajax y recibir mi Knockout de respuesta JSON no está actualizando todas mis enlaces ... como si los mapeos observables/
Si incluyo un ko.applybindings adicional (ViewModel); en el éxito Las cosas funcionan ... sin embargo, los problemas surgen con múltiples enlaces y estoy seguro de que esta no es la solución correcta.
Este es el HTML/plantilla/enlaces
<!-- Start Form -->
<form action="@Url.Action("Edit")" data-bind="submit: save">
<div id="editListing" data-bind="template: 'editListingTemplate'"></div>
<div id="saveListing" class="end-actions">
<button type="submit">Save Listings</button>
</div>
</form>
<!-- End Form -->
<!-- Templates -->
<script type="text/html" id="editListingTemplate">
<div class="warning message error" data-bind="visible: Response.HasWarning">
<span>Correct the Following to Save</span>
<ul>
{{each(i, warning) Response.BusinessWarnings}}
<li data-bind="text: Message"></li>
{{/each}}
</ul>
</div>
<fieldset>
<legend>Key Information</legend>
<div class="editor-label">
<label>Project Name</label>
</div>
<div class="editor-field">
<input data-bind="value: Project_Name" class="title" />
</div>
</fieldset>
</script>
<!-- End templates -->
Y este es el knockout/script
<script type="text/javascript">
@{ var jsonData = new HtmlString(new JavaScriptSerializer().Serialize(Model)); }
var initialData = @jsonData;
var viewModel = ko.mapping.fromJS(initialData);
viewModel.save = function ()
{
this.Response = null;
var data = ko.toJSON(this);
$.ajax({
url: '@Url.Action("Edit")',
contentType: 'application/json',
type: "POST",
data: data,
dataType: 'json',
success: function (result) {
ko.mapping.updateFromJS(viewModel, result);
}
});
}
$(function() {
ko.applyBindings(viewModel);
});
</script>
Y esta es la respuesta que JSON devolvió de la solicitud exitosa, incluidos los mensajes de validación.
{
"Id": 440,
"Project_Name": "",
"Response": {
"HasWarning": true,
"BusinessWarnings": [
{
"ExceptionType": 2,
"Message": "Project is invalid."
}, {
"ExceptionType": 1,
"Message": "Project_Name may not be null"
}
]
}
}
ACTUALIZAR
Demo de violinista Es un ejemplo en vivo recortado de lo que estoy experimentando. Tengo la actualización de Project_Name con el JSON devuelto, pero el objeto ViewModel.Sponse y las propiedades no se están actualizando a través de sus enlaces de datos. Específicamente respuesta.haswarning ().
He cambiado de nuevo a ko.mapping.updateFromJS porque en mi controlador estoy devolviendo específicamente JSON (ViewModel).
Limpió mi código/pregunta inicial para que coincida con la demostración.
Solución
Supongo que la respuesta está reservada cuando cambio "respuesta" a "resp", todo salió bien. Ver http://jsfiddle.net/bbzvm/
Otros consejos
¿No debería usar ko.mapping.updateFromJson en su evento de éxito? Capítulo Trabajando con JSON Strings En el sitio de mapeo de knockout dice:
Si su llamada AJAX devuelve una cadena JSON (y no la deserializa en un objeto JavaScript), puede usar las funciones ko.mapping.fromjson y ko.mapping.updatefromjson para crear y actualizar su modelo de vista en su lugar.