ajax - construcción dinámica de formularios con knockoutjs
asp.net-mvc-3 knockout.js (1)
Para realizar un seguimiento de los cambios, puede utilizar dirty flag
de este artículo: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html .
Crea el siguiente modelo de vista:
function FormField(data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Type = ko.observable(data.Type);
self.Options = ko.observableArray(data.Type != ''text'' ? data.Options : []);
self.Default = ko.observable(data.Default);
}
function ViewModel(data) {
var self = this;
self.Fields = ko.observableArray(ko.utils.arrayMap(data, function(item) {
return new FormField(item);
}));
self.dirtyFlag = new ko.dirtyFlag(this);
self.isDirty = ko.computed(function (){
if (self.dirtyFlag.isDirty())
{
alert("Value changed!");
// Do async update.
}
});
}
Marcado de HTML:
<div data-bind="foreach: Fields">
<b data-bind="text: Name"></b>
<!--ko if: Type() == "combo"-->
<select data-bind="options: Options, value: Default"></select> <!--/ko-->
<!--ko if: Type() == "radio"-->
<div data-bind="foreach: Options">
<input type="radio" value="cherry" data-bind="value: $data, checked: $parent.Default" />
<span data-bind="text: $data"></span>
</div>
<!--/ko-->
<!--ko if: Type() == "text"-->
<input type="text" data-bind="value: Default"></input>
<!--/ko-->
<br/>
</div>
Aquí está trabajando fiddle: http://jsfiddle.net/vyshniakov/CWTTR/
EDITAR:
Aquí hay respuestas sobre sus preguntas si las entendí bien:
Para publicar todos los campos en el servidor, puede usar la función ko.toJSON(self)
. Tu llamada ajax tendrá el siguiente aspecto:
$.ajax({
type: "POST",
url: "controller/action",
contentType: ''application/json'',
data: JSON.stringify(ko.toJSON(self)),
success: function(result) {
self.HiddenElements(result);
}
});
Mire el violín actualizado para ver cómo ocultar algunos campos dependiendo de la respuesta del servidor: http://jsfiddle.net/vyshniakov/CWTTR/1/ .
Necesito construir un formulario dinámico desde la base de datos. Tengo la siguiente Entidad para definir campos de formulario sobre la marcha:
public class FormField {
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; } // Possible values are: ''Radio'',''Combo'',''Text''. A dropdown will be created for a Combo type of element, a radio set for Radio type of element and a text input for Text type of element.
public string Options { get; set; } // Only relevant in case of Radio/Combo type
public string Default { get; set; } // Default value in case of Type ''Text'' and selected value in case of Type ''Radio/Combo''
public string Blankout { get; set; }// An expression to define when this field should be hidden
}
/* A sample JSON array (from the DB) to build the form would be:
[
{ Name:"Gender", Type:"radio", Options:["Male","Female","Unknown"], Default:"Male", Blankout:"Never" },
{ Name:"Age", Type:"text", Options:"None", Default:15, Blankout:"Never" },
{ Name:"Neighbourhood", Type:"Combo", Options:["Eastern","Western","Northern","Southern","Central"], Default:"Central", Blankout:"if (Age < 40 or Voted=''Obama'')" },
{ Name:"Voted", Type:"Combo", Options:["Obama","Romney","Harry Potter"], Default:"Harry Potter", Blankout:"if ((Gender=''Female'' and Age < 15) or Neighbourhood=''Eastern''" }
]
*/
Puedo construir una forma dinámica desde los registros ''FormField'' en DB, PERO el problema es que necesito rastrear los cambios en los valores de cualquier campo de formulario, y cuando ocurre un cambio en el valor, necesito enviar todos los datos del formulario al servidor ( asincrónicamente) para evaluar la fórmula ''Blankout'' en el Servidor. Si hago esto de cambio de seguimiento sin KnockoutJS no responde y se vuelve muy complejo. He pasado por varios tutoriales de KnockoutJS, pero no pude encontrar la manera de organizar mi ViewModel para este problema en particular.
Cualquier ayuda sería apreciada.
Actualización 1
Intenté publicar los datos de este formulario en el controlador utilizando el siguiente código:
$.ajax({
type: "POST",
url: "/MyController/GetBlankoutElements",
contentType: ''application/json'',
dataType: ''json'',
data: JSON.stringify(ko.toJSON(self)),
success: function(result) {
alert(result);
//self.HiddenElements(result.split('',''));
}
});
En mi controlador, he intentado seguir el código:
[HttpPost]
public ActionResult GetBlankoutElements(List<MyFieldViewModel> Fields)
{
return Json(Fields); // List, Fields is null here
}
Ella es a lo que se parece la clase MyFieldViewModel:
public class MyFieldViewModel
{
public string Title { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Default { get; set; }
public string[] Options { get; set; }
}
He intentado consejos descritos en Publicar una matriz de objetos a través de JSON a ASP.Net MVC3
A continuación está la información de Json que se imprime cuando ejecuto la alerta (ko.toJSON (self))
{"Fields":
[{"Title":"CCType","Name":"CCType","Type":"Radio","Default":"Enterprise","Options":["Enterprise","Express","CVP","PCCE"]},{"Title":"Industry","Name":"Industry","Type":"Combo","Default":"Banks","Options":["Banks","ServiceProvider","Outsourcer","Airlines","Utilities","Government","Retail"]},{"Title":"Customer Lab","Name":"CustomerLab","Type":"Combo","Default":"0","Options":["0","1"]},{"Title":"No of Agents","Name":"Agents","Type":"Text","Default":"if(c.CCType==/"CVP/") then 10 else 25","Options":[]},{"Title":"ExpLicType","Name":"ExpLicType","Type":"Radio","Default":"if(c.CCType==/"Express/") then /"Enhanced/" else /"None/"","Options":["None","Premium","Standard","Enhanced"]},{"Title":"Multimedia","Name":"Multimedia","Type":"Combo","Default":"WIM","Options":["None","EIM","WIM","EIM&WIM","BSMediaRouting","MCAL"]}],
"HiddenElements":[]
}
Lo que necesito es solo el nombre del campo y su valor seleccionado por el usuario, y estoy confundido, incluso si obtengo estos datos json asignados a mi clase MyFieldViewModel , ¿cómo obtendría los VALORES seleccionados?
Actualización 2 (Mapeo de datos JSON funcionó)
Cuando cambié
data: JSON.stringify(ko.toJSON(self))
con datos: ko.toJSON (auto)
El mapeo funcionó perfectamente en mi controlador, como puede ver en la siguiente captura de pantalla:
Ahora, el problema persiste, el objetivo de publicar el formulario fue actualizar el servidor con la entrada del usuario en el formulario, es decir, valores contra cada elemento del campo de formulario. ¿Cómo publico los valores seleccionados / tipados actuales de los campos de formulario? Por ejemplo, en la captura de pantalla anterior, puedo ver el valor predeterminado pero no el valor seleccionado actual.