¿Cómo utilizar knockout.js con ASP.NET MVC ViewModels?

129

Generosidad

Ha pasado un tiempo y todavía tengo un par de preguntas pendientes. Espero que al agregar una recompensa, tal vez estas preguntas sean respondidas.

  1. ¿Cómo se usan los ayudantes html con knockout.js?
  2. ¿Por qué se necesitaba un documento listo para que funcione? (Ver primera edición para más información)

  3. ¿Cómo hago algo como esto si estoy usando el mapeo knockout con mis modelos de vista? Como no tengo una función debido a la asignación.

    function AppViewModel() {
    
        // ... leave firstName, lastName, and fullName unchanged here ...
    
        this.capitalizeLastName = function() {
    
        var currentVal = this.lastName();        // Read the current value
    
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    
    };
    
  4. Quiero usar complementos, por ejemplo, quiero poder revertir los observables como si un usuario cancela una solicitud Quiero poder volver al último valor. Según mi investigación, esto parece ser logrado por personas que crean complementos como editables

    ¿Cómo uso algo así si estoy usando mapeo? Realmente no quiero ir a un método en el que tengo en mi vista mapeo manual donde mapeo cada campo MVC viewMode a un campo modelo KO, ya que quiero el menor javascript en línea posible y eso parece el doble de trabajo y eso es Por eso me gusta ese mapeo.

  5. Me preocupa que para facilitar el trabajo (mediante el mapeo) pierda una gran cantidad de KO pero, por otro lado, me preocupa que el mapeo manual sea mucho trabajo y haga que mis vistas contengan demasiada información y en el futuro podría ser más difícil de mantener (por ejemplo, si elimino una propiedad en el modelo MVC, también tengo que moverla en el modelo de vista KO)


Publicación original

Estoy usando asp.net mvc 3 y estoy investigando la eliminación, ya que se ve muy bien, pero me está costando descubrir cómo funciona con asp.net mvc, especialmente ver modelos.

Para mí en este momento hago algo como esto

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

Tendría un Vm que tiene algunas propiedades básicas como CourseName y tendrá una validación simple encima. El modelo Vm también puede contener otros modelos de vista si es necesario.

Luego pasaría este Vm a la Vista donde usaría los ayudantes html para ayudarme a mostrarlo al usuario.

@Html.TextBoxFor(x => x.CourseName)

Es posible que tenga algunos bucles foreach o algo para obtener los datos de la colección de Modelos de vista de estudiante.

Luego, cuando envíe el formulario, usaría jquery y lo serialize arrayenviaría a un método de acción del controlador que lo vincularía de nuevo al modelo de vista.

Con knockout.js todo es diferente, ya que ahora tiene modelos de vista para él y de todos los ejemplos que vi, no usan ayudantes html.

¿Cómo utiliza estas 2 características de MVC con knockout.js?

Encontré este video y brevemente (últimos minutos del video a las 18:48) sirve para usar modelos de vista básicamente teniendo un script en línea que tiene el modelo de vista knockout.js al que se le asignan los valores en ViewModel.

¿Es esta la única manera de hacerlo? ¿Qué tal en mi ejemplo con tener una colección de modelos de vista? ¿Tengo que tener un bucle foreach o algo para extraer todos los valores y asignarlo a knockout?

En cuanto a los ayudantes html, el video no dice nada sobre ellos.

Estas son las 2 áreas que me confunden muchísimo, ya que no muchas personas parecen hablar de eso y me deja confundido sobre cómo los valores iniciales y todo está llegando a la vista cuando algún ejemplo es solo un ejemplo de valor codificado.


Editar

Estoy intentando lo que ha sugerido Darin Dimitrov y esto parece funcionar (aunque tuve que hacer algunos cambios en su código). No estoy seguro de por qué tuve que usar el documento listo, pero de alguna manera no todo estaba listo sin él.

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

Tuve que envolverlo alrededor de un documento jquery listo para que funcione.

También recibo esta advertencia. No estoy seguro de qué se trata.

Warning 1   Conditional compilation is turned off   -> @Html.Raw

Así que tengo un punto de partida, supongo que al menos se actualizará cuando haya jugado un poco más y cómo funciona.

Estoy tratando de seguir los tutoriales interactivos, pero en su lugar utilizo un ViewModel.

Aún no estoy seguro de cómo abordar estas partes

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

o

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };


Editar 2

Pude resolver el primer problema. No tengo idea del segundo problema. Sin embargo, sin embargo. ¿Alguien tiene alguna idea?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

Controlador

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }
chobo2
fuente
2
Acabo de escribir una publicación de blog para responder a otra pregunta similar: roysvork.wordpress.com/2012/12/09/… Puede que no responda su pregunta por completo, pero le da una buena idea de cómo podrían funcionar las cosas. Espero seguir con esto con otra publicación en un futuro no muy lejano. No dude en hacerme cualquier pregunta en los comentarios en la publicación o aquí si necesita más información.
más allá del código

Respuestas:

180

Creo que he resumido todas sus preguntas, si me perdí algo, hágamelo saber ( si pudiera resumir todas sus preguntas en un solo lugar sería bueno =))

Nota. Compatibilidad con el ko.editablecomplemento agregado

Descargar el código completo

¿Cómo se usan los ayudantes html con knockout.js?

Esto es facil:

@Html.TextBoxFor(model => model.CourseId, new { data_bind = "value: CourseId" })

Dónde:

  • value: CourseIdindica que está vinculando la valuepropiedad del inputcontrol con la CourseIdpropiedad de su modelo y su modelo de script

El resultado es:

<input data-bind="value: CourseId" data-val="true" data-val-number="The field CourseId must be a number." data-val-required="The CourseId field is required." id="CourseId" name="CourseId" type="text" value="12" />

¿Por qué se necesitaba un documento listo para que funcione? (Ver primera edición para más información)

Todavía no entiendo por qué necesita usar el readyevento para serializar el modelo, pero parece que simplemente es obligatorio (aunque no se preocupe por eso)

¿Cómo hago algo como esto si estoy usando el mapeo knockout con mis modelos de vista? Como no tengo una función debido a la asignación.

Si entiendo correctamente, debe agregar un nuevo método al modelo KO, bueno, eso es fácil de combinar modelos

Para más información, en la sección -Mapeo de diferentes fuentes-

function viewModel() {
    this.addStudent = function () {
        alert("de");
    };
};

$(function () {
    var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
    var mvcModel = ko.mapping.fromJSON(jsonModel);

    var myViewModel = new viewModel();
    var g = ko.mapping.fromJS(myViewModel, mvcModel);

    ko.applyBindings(g);
});

Sobre la advertencia que estabas recibiendo

Advertencia 1 La compilación condicional está desactivada -> @ Html.Raw

Necesitas usar comillas

Compatibilidad con el complemento ko.editable

Pensé que iba a ser más complejo, pero resulta que la integración es realmente fácil, para que su modelo sea editable solo agregue la siguiente línea: (recuerde que en este caso estoy usando un modelo mixto, desde el servidor y agregar extensión en el cliente y lo editable simplemente funciona ... es genial):

    ko.editable(g);
    ko.applyBindings(g);

Desde aquí solo necesita jugar con sus enlaces usando las extensiones agregadas por el complemento, por ejemplo, tengo un botón para comenzar a editar mis campos de esta manera y en este botón comienzo el proceso de edición:

    this.editMode = function () {
        this.isInEditMode(!this.isInEditMode());
        this.beginEdit();
    };

Luego tengo botones de confirmación y cancelación con el siguiente código:

    this.executeCommit = function () {
        this.commit();
        this.isInEditMode(false);
    };
    this.executeRollback = function () {
        if (this.hasChanges()) {
            if (confirm("Are you sure you want to discard the changes?")) {
                this.rollback();
                this.isInEditMode(false);
            }
        }
        else {
            this.rollback();
            this.isInEditMode(false);
        }
    };

Y finalmente, tengo un campo para indicar si los campos están en modo de edición o no, esto es solo para vincular la propiedad enable.

this.isInEditMode = ko.observable(false);

Sobre su pregunta de matriz

Es posible que tenga algunos bucles foreach o algo para obtener los datos de la colección de Modelos de vista de estudiante.

Luego, cuando enviaba el formulario, usaba jquery y serializaba la matriz y lo enviaba a un método de acción del controlador que lo vincularía de nuevo al modelo de vista.

Puede hacer lo mismo con KO, en el siguiente ejemplo, crearé la siguiente salida:

ingrese la descripción de la imagen aquí

Básicamente aquí, tiene dos listas, creadas usando Helpersy vinculadas con KO, tienen un dblClickevento vinculado que, cuando se activa, elimina el elemento seleccionado de la lista actual y lo agrega a la otra lista, cuando publica en Controllerel contenido de cada la lista se envía como datos JSON y se vuelve a adjuntar al modelo de servidor

Pepitas:

Externos guiones .

Código del controlador

    [HttpGet]
    public ActionResult Index()
    {
        var m = new CourseVM { CourseId = 12, CourseName = ".Net" };

        m.StudentViewModels.Add(new StudentVm { ID = 545, Name = "Name from server", Lastname = "last name from server" });

        return View(m);
    }

    [HttpPost]
    public ActionResult Index(CourseVM model)
    {
        if (!string.IsNullOrWhiteSpace(model.StudentsSerialized))
        {
            model.StudentViewModels = JsonConvert.DeserializeObject<List<StudentVm>>(model.StudentsSerialized);
            model.StudentsSerialized = string.Empty;
        }

        if (!string.IsNullOrWhiteSpace(model.SelectedStudentsSerialized))
        {
            model.SelectedStudents = JsonConvert.DeserializeObject<List<StudentVm>>(model.SelectedStudentsSerialized);
            model.SelectedStudentsSerialized = string.Empty;
        }

        return View(model);
    }

Modelo

public class CourseVM
{
    public CourseVM()
    {
        this.StudentViewModels = new List<StudentVm>();
        this.SelectedStudents = new List<StudentVm>();
    }

    public int CourseId { get; set; }

    [Required(ErrorMessage = "Course name is required")]
    [StringLength(100, ErrorMessage = "Course name cannot be this long.")]
    public string CourseName { get; set; }

    public List<StudentVm> StudentViewModels { get; set; }
    public List<StudentVm> SelectedStudents { get; set; }

    public string StudentsSerialized { get; set; }
    public string SelectedStudentsSerialized { get; set; }
}

public class StudentVm
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Lastname { get; set; }
}

Página CSHTML

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>CourseVM</legend>

        <div>
            <div class="editor-label">
                @Html.LabelFor(model => model.CourseId)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseId, new { data_bind = "enable: isInEditMode, value: CourseId" })
                @Html.ValidationMessageFor(model => model.CourseId)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.CourseName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseName, new { data_bind = "enable: isInEditMode, value: CourseName" })
                @Html.ValidationMessageFor(model => model.CourseName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(model => model.StudentViewModels);
            </div>
            <div class="editor-field">

                @Html.ListBoxFor(
                    model => model.StudentViewModels,
                    new SelectList(this.Model.StudentViewModels, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: StudentViewModels, optionsText: 'Name', value: leftStudentSelected, event: { dblclick: moveFromLeftToRight }"
                    }
                )
                @Html.ListBoxFor(
                    model => model.SelectedStudents,
                    new SelectList(this.Model.SelectedStudents, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: SelectedStudents, optionsText: 'Name', value: rightStudentSelected, event: { dblclick: moveFromRightToLeft }"
                    }
                )
            </div>

            @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
            @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
            @Html.HiddenFor(model => model.StudentsSerialized, new { data_bind = "value: StudentsSerialized" })
            @Html.HiddenFor(model => model.SelectedStudentsSerialized, new { data_bind = "value: SelectedStudentsSerialized" })
        </div>

        <p>
            <input type="submit" value="Save" data-bind="enable: !isInEditMode()" /> 
            <button data-bind="enable: !isInEditMode(), click: editMode">Edit mode</button><br />
            <div>
                <button data-bind="enable: isInEditMode, click: addStudent">Add Student</button>
                <button data-bind="enable: hasChanges, click: executeCommit">Commit</button>
                <button data-bind="enable: isInEditMode, click: executeRollback">Cancel</button>
            </div>
        </p>
    </fieldset>
}

Guiones

<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ko.editables.js")" type="text/javascript"></script>

<script type="text/javascript">
    var g = null;
    function ViewModel() {
        this.addStudent = function () {
            this.StudentViewModels.push(new Student(25, "my name" + new Date(), "my last name"));
            this.serializeLists();
        };
        this.serializeLists = function () {
            this.StudentsSerialized(ko.toJSON(this.StudentViewModels));
            this.SelectedStudentsSerialized(ko.toJSON(this.SelectedStudents));
        };
        this.leftStudentSelected = ko.observable();
        this.rightStudentSelected = ko.observable();
        this.moveFromLeftToRight = function () {
            this.SelectedStudents.push(this.leftStudentSelected());
            this.StudentViewModels.remove(this.leftStudentSelected());
            this.serializeLists();
        };
        this.moveFromRightToLeft = function () {
            this.StudentViewModels.push(this.rightStudentSelected());
            this.SelectedStudents.remove(this.rightStudentSelected());
            this.serializeLists();
        };
        this.isInEditMode = ko.observable(false);
        this.executeCommit = function () {
            this.commit();
            this.isInEditMode(false);
        };
        this.executeRollback = function () {
            if (this.hasChanges()) {
                if (confirm("Are you sure you want to discard the changes?")) {
                    this.rollback();
                    this.isInEditMode(false);
                }
            }
            else {
                this.rollback();
                this.isInEditMode(false);
            }
        };
        this.editMode = function () {
            this.isInEditMode(!this.isInEditMode());
            this.beginEdit();
        };
    }

    function Student(id, name, lastName) {
        this.ID = id;
        this.Name = name;
        this.LastName = lastName;
    }

    $(function () {
        var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
        var mvcModel = ko.mapping.fromJSON(jsonModel);

        var myViewModel = new ViewModel();
        g = ko.mapping.fromJS(myViewModel, mvcModel);

        g.StudentsSerialized(ko.toJSON(g.StudentViewModels));
        g.SelectedStudentsSerialized(ko.toJSON(g.SelectedStudents));

        ko.editable(g);
        ko.applyBindings(g);
    });
</script>

Nota: Acabo de agregar estas líneas:

        @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
        @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })

Porque cuando envío el formulario mis campos están deshabilitados, por lo que los valores no se transmitieron al servidor, por eso agregué un par de campos ocultos para hacer el truco

Jupaol
fuente
Hmm muy informativo. Por su respuesta y la respuesta de Pual, creo que casi obtuve respuestas a todas mis preguntas, excepto cómo usar complementos como editables. Esperemos que alguien sepa cómo puedo usar esto.
chobo2
1
Acabo de agregar compatibilidad con el ko.editablescomplemento, puede verificar la respuesta actualizada o, si lo desea, puede descargar todo el proyecto para ejecutarlo localmente
Jupaol
Lo comprobaré cuando pueda. ¿Tuvo que cambiar mucho para que funcione? Me pregunto si para cada complemento encuentro si tendré que cambiarlo y luego mantener mi propia versión.
chobo2
No Te sorprenderás, está casi
listo para usar
1
Gracias a todos, aprendí varias estrategias nuevas de su respuesta. ¡Prestigio!
sky-dev
23

Puede serializar su modelo de vista ASP.NET MVC en una variable de JavaScript:

@model CourseVM
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));
    // go ahead and use the model javascript variable to bind with ko
</script>

Hay muchos ejemplos en la documentación de eliminación que puede revisar.

Darin Dimitrov
fuente
1
Sí, revisé el tutorial interactivo que tienen en el sitio, pero realmente nunca veo nada que ver con asp.net mvc. Veo que también tienen algunos complementos de mapeo, pero no estoy seguro de cómo encaja eso. En su ejemplo, ¿cómo lo vincularía al modelo de eliminación (en otro script). Realmente quiero tener el menor javascript en línea posible (no es preferible pero supongo que no es posible)
chobo2
2
¿Qué problema estás tratando de resolver? Si desea vistas MVC y está satisfecho con cómo usarlas, puede quedarse allí. Si desea vinculación y manipulación de datos del lado del cliente, entonces KO es una gran opción. Puede generar su modelo de vista KO a partir de su código MVC como muestra esta respuesta. Toma el vm y lo serializa a json. Luego, en el cliente, puede asignar los resultados a un modelo de vista de JavaScript. Luego, vincule el modelo de vista a la vista y ya está todo listo. La clave es que MVC y KO no tienen que estar acoplados de ninguna manera, a menos que usted lo desee. Todo depende del problema que intente resolver.
John Papa
1
Es normal que no vea nada que ver con asp.net mvc. Knockout es un marco del lado del cliente. No sabe ni le importa qué idioma del lado del servidor está utilizando. Esos 2 marcos deben estar absolutamente desacoplados.
Darin Dimitrov
@ JohnPapa: me gusta la forma en que hago las cosas ahora, pero también me gusta aprender cosas nuevas (veo que KO puede ser muy útil en algunas situaciones). Sé que KO es un script del lado del cliente, pero para mí los veo trabajando juntos. Actualmente genero mis vistas usando modelos de vista y ayudantes html. Entonces, en mi opinión, KO necesita trabajar junto con esto. Por ejemplo, digamos que tienes un diálogo de edición. ¿Cómo diseñaría y llenaría los valores de una base de datos en esos campos? Si estuviera usando mi camino, sería una vista de ayudantes html que tiene un modelo de vista. Rellenaría el modelo de vista y lo enviaría a través del Método de acción y lo usaría.
chobo2
1
@ chobo2, knockout es un marco del lado del cliente. Utiliza modelos de vista en el cliente para implementar el patrón MVC en el cliente. El servidor está desacoplado. También puede usar ver modelos en él. Son solo 2 lugares diferentes. Si tiene alguna lógica compleja que desea implementar en el cliente usando javascript, la eliminación puede simplificar esto. De lo contrario, honestamente, no lo necesitas.
Darin Dimitrov
2

Para lograr las propiedades calculadas adicionales después de la asignación del servidor, deberá mejorar aún más sus modelos de vista en el lado del cliente.

Por ejemplo:

var viewModel = ko.mapping.fromJS(model);

viewModel.capitalizedName = ko.computed(function() {...}, viewModel);

Por lo tanto, cada vez que asigne desde JSON sin procesar, deberá volver a aplicar las propiedades calculadas.

Además, el complemento de mapeo proporciona la capacidad de actualizar gradualmente un modelo de vista en lugar de recrearlo cada vez que va y viene (use un parámetro adicional en fromJS):

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

Y eso ejecuta una actualización de datos incremental en su modelo de solo propiedades que están mapeadas. Puede leer más sobre eso en la documentación de mapeo

Usted mencionó en los comentarios sobre la respuesta de Darin el paquete FluentJSON . Soy el autor de eso, pero su caso de uso es más específico que ko.mapping. En general, solo lo usaría si sus modelos de vista son unidireccionales (es decir, servidor -> cliente) y luego los datos se vuelven a publicar en algún formato diferente (o no en absoluto). O si su modelo de vista de JavaScript debe estar en un formato sustancialmente diferente del modelo de su servidor.

Paul Tyng
fuente
Hmm, entonces supongo que FluentJSON no es para mí, ya que mis modelos de vista la mayor parte del tiempo van en ambos sentidos (generalmente lo envío de vuelta a través de json y luego lo enlazo al modelo de vista en el parámetro del método de acción). ¿Sabes cómo podría usar esos complementos que mencioné como editables? Finalmente, ¿estoy perdiendo algún tipo de funcionalidad al usar el mapeo e intentar usar mi modelo de vista en lugar de no usarlo?
chobo2
No he usado ninguno de los complementos, así que no estoy seguro. Lo que hice en el pasado fue suscribirme a cada cambio y mantener una pila de estados de modelos de vista serializados a los que presionaría para cambiar y hacer deshacer ( vea esta pregunta ).
Paul Tyng
el mapeo no lo aleja de ninguna funcionalidad, solo necesita asegurarse y observar sus convenciones sobre cómo maneja el mapeo hacia y desde JS para que todo funcione bien juntos.
Paul Tyng
Bueno, la respuesta aceptada a la pregunta que publicaste es básicamente cuál sería el complemento. Eso es lo que me confunde, ya que puedes ver que crean un modelo de vista y luego usan su función que hicieron (ko.observableArrayWithUndo ([])). Si estoy haciendo un mapeo, no sé cómo hacerlo. Lo único que me viene a la mente es escribir mi propio mapeo (lo que dudo que pueda en este momento) que tiene deshacer observable o mapear cada propiedad, pero luego básicamente tengo modelos de vista duplicados, uno para el lado del servidor y otro para el cliente y estoy miedo que se volverá
imposible de mantener
Ah, sí, lo siento, estaba hablando de mi respuesta a esa pregunta, lo siento debería haber vinculado directamente.
Paul Tyng