Pregunta

Estoy usando Knockout (KO) en mi proyecto MVC. Creo un modelo de MVC (para una cuadrícula) en el servidor y pasarlo a la vista. En la vista, se enloqueció y se convierte en un modelo KO (usando ko.mapping) que a su vez se usa para la encuadernación. Que la unión se usa luego en HTML para la creación de la cuadrícula.

Así es como se ve mi modelo de cuadrícula de MVC, que a su vez se convierte en el modelo KO correspondiente por ko.mapping:

public class GridModel
    {
        /// <summary>
        /// Grid body for the grid.
        /// </summary>
        public GridBodyModel GridBodyModel { get; set; }

        /// <summary>
        /// Grid context.
        /// </summary>
        public GridContext GridContext { get; set; }

        /// <summary>
        /// Grid header for the grid.
        /// </summary>
        public GridHeaderModel GridHeader { get; set; }
    }

public class GridBodyModel
    {
        /// <summary>
        /// List of grid body rows.
        /// </summary>
        public IList<GridRowModel> Rows { get; set; }
    }


public class GridContext
    {
        /// <summary>
        /// Total number of pages. Read-only.
        /// </summary>
        public int TotalPages{ get; set; }
    }

public class GridHeaderModel
    {
        /// <summary>
        /// List of grid header cells.
        /// </summary>
        public IList<GridHeaderCellModel> Cells { get; set; }
    }

Como está claro, el modelo principal de la clase de clase se hace de las siguientes clases que están presentes como propiedades:

GridbodyModel: tiene lista de filas que se presentarán en el cuerpo de la cuadrícula.

GridContext: tiene un número total de páginas como una propiedad. También tiene otras propiedades, pero que está fuera de alcance de esta discusión.

GridHeeModel: tiene una lista de celdas que deben mostrarse en el encabezado de la cuadrícula.

Luego tengo este script que se ejecutará en la carga de la página fresca.

$(document).ready(function () {
        // Apply Knockout view model bindings when document is in ready state.
        ko.applyBindings(Global_GridKOModel, document.getElementById("gridMainContainer"));
    });

// Serialize the server model object. It will be used to create observable model.
Global_GridKOModel = ko.mapping.fromJS (<%= DataFormatter.SerializeToJson(Model) %>);

global_gridkomodel es la variable de JavaScript global. modelo es el modelo de cuadrícula MVC que viene del servidor.

Un usuario puede realizar una búsqueda adicional en la página nuevamente. Yo manejo esto publicando nuevos criterios de búsqueda a través de AJAX. En esta publicación se crea un nuevo modelo de MVC y se envía a la respuesta AJAX. Este nuevo modelo MVC se usa simplemente para actualizar global_gridkomodel usando ko.mapping, que a su vez actualiza la cuadrícula (con datos nuevos) que se construyó anteriormente en la carga de la página fresca. Así es como lo estoy haciendo.

$.ajax({
        url: destUrl,
        data: dataToSend
        success: function (result) {
            ko.mapping.fromJS(result, Global_GridKOModel);
        },
        error: function (request, textStatus, errorThrown) {
            alert(request.statusText);
        }
    });

Todo está funcionando bien, excepto en el siguiente escenario.

Se hace una solicitud AJAX para la cual no se devuelve ningún resultado, es decir, GridbodyModel y GridHeaderModel es nulo en el modelo GridModel . Esa cuadrícula de tiempo muestra que no se ha encontrado ningún registro. Esto es correcto. Esto sucede por la siguiente encuadernación HTML.

<!-- When no record is found. -->
<div data-bind="ifnot: GridContext.GridPager.TotalPages() > 0">
    No record(s) were found.
</div>

<!-- This is actual grid table container. This is binded when records are found -->
<div data-bind="if: GridContext.TotalPages() > 0">

Grid construction happens here

</div>

Ahora, después de esto, si se hace otra solicitud de AJAX, pero se devuelven estos registros de tiempo (he revisado la respuesta con Firebug y se confirma que los registros se devuelven). Esta ocasión de redes de tiempo ocurre en la que se accede a varias matrices observables. Por ejemplo, para construir un buscapersonas para la cuadrícula siguiente es una pieza de unión HTML que escribí.

<td data-bind="attr:{colspan: GridHeader.Cells().length }">

Esta vez, KO lanza un error posterior que se puede ver en Firebug.

incapaz de analizar los enlaces. Mensaje: TypeError: GridHeader.cells no es una función; Vinanzas Valor: ATTR: {Colspan: GridHeader.cells (). Longitud}

funciona bien, mientras se devuelven registros, pero se rompe después de que no se devuelve ningún registro como se explica anteriormente. Tenga en cuenta que GridHeader fue null en una respuesta anterior cuando no se devolvieron registros. Huelo algo de pescado en ko.mapping. Creo que hay algún problema al mapear la matriz observable.

Entonces, ¿qué es lo que no estoy haciendo bien? ¿Alguien por favor?

No dude en solicitar aclaraciones si no he mencionado las cosas claramente.

gracias de antemano.

¿Fue útil?

Solución

La razón real de comportamiento es que originalmente GRIDHEADER es un objeto JavaScript, pero cuando su llamada de devolución se mapee con NULL para la propiedad de GridHeader, será observable con valor nulo, y en todas las actualizaciones futuras, seguirá siendo un observable.

Las soluciones son (Elija una):

  1. No devuelva los valores nulos para los modelos infantiles (devuelva los objetos vacíos), creo que es una forma preferida
  2. o - antes de llamar al mapa, correr Global_gridkomodel.gridheader= null; (Esto se asegurará de que después de la actualización de GridHeader no será observable)
  3. o - después del mapeo, llame Global_gridkomodel.gridheader= ko.unwrapobobservable (global_gridkomodel.gridheader);

    Explicación completa del comportamiento que tiene está en el código a continuación (Copiar en JSFiddle - http:// jsfiddle. NET / NICHOLSKY / ZRBUL / 9 / )

    console.log('step1');
    var vm = ko.mapping.fromJS({ body: { children: [ 1, 2, 3]} });
    console.log(vm.body.children()[1]); //prints 2
    
    console.log('step2');
    ko.mapping.fromJS({ body: { children: [ 4, 5, 6]} }, vm);
    console.log(vm.body.children()[1]); //prints 5
    
    console.log('step3');
    //after next call, vm.body is no longer variable - it is now observable
    ko.mapping.fromJS({ body: null }, vm);
    console.log(vm.body); //prints observable
    console.log(vm.body()); //prints null
    
    console.log('step4');
    //and it will remain observable for next call
    ko.mapping.fromJS({ body: { children: [ 7, 8, 9]} }, vm);
    console.log(vm.body().children()[1]); //prints 8
    console.log(vm.body().children().length); //prints 3
    console.log(vm.body); //prints observable function body
    console.log(vm.body()); //prints object
    
    //workaround for null issue - we can reset it to be null instead of null observable
    //and it will get original behavior
    vm.body = null;
    console.log('step5');    
    ko.mapping.fromJS({ body: { children: [ 7, 8, 9]} }, vm);
    console.log(vm.body.children()[1]); //prints 8 - body is no longer observable again
    ​
    

    Para mí parece un problema de diseño del complemento de mapeo, no pude encontrar una manera de personalizar la asignación de las propiedades de ViewModel para niños para asegurarse de que no se convertirán en observables si son nulos ('Copiar' funcionalidad hará todo Contenido interno como no observable, desafortunado).

Otros consejos

Lo pensé anoche. En realidad, esto fue un error muy básico que estaba haciendo. Estaba tratando de acceder a una matriz después de configurarla en NULL. Lo explicaré como.

Cuando se devolvió el resultado, se definió el tiempo de la TimeHeaderModel y las células ilistas en ella, no fueron nulas. Ese tiempo ko.mapping pudo convertir el modelo y crear el modelo y Arrary por dentro. Pero cuando se hicieron cualquier solicitud AJAX, en la que se devolvió el resultado de NOO y el GridHeeTermodel fue nulo, obviamente, las células ilícuales también fueron nulas. Ese tiempo ko.mapping hizo lo mismo, el modelo KO que actualizó, estableció GridHeeModel a NULLO, y las células de la matriz observable en el interior no estaban actuales, lo que es tan bueno como NULL. Ahora, cuando hice otra solicitud AJAX con algunos registros devueltos, el ko.mapping intentó actualizar las células de matriz observable que no existían (o se estableció en NULL) en el modelo KO en el cliente, falló. Si en lugar de Ajax, fue una carga fresca de la página, todo habría funcionado. Por lo tanto, la solución no debe devolver ninguna enumeración (aquellos que se convertirán en matriz observable) sin inicializar al cliente para la actualización del modelo KO. Por lo tanto, cuando no se devolverá ningún registro, me aseguré de que GridHeeTermodel no sea nulo y también se aseguró de que las células ilícuales se inicialicen, aunque no contenía ningún elemento. Esto solucionó el problema.

Este problema podría explicarse con el siguiente ejemplo.

public class Demo
{
    public IList<string> DemoArray;
}

public class DemoUser
{
    public void UseDemo()
        {
            var demoInstance = new Demo();
            demoInstance.DemoArray.Add("First Element");
        }
}

aquí en el método usado () Hemos inicializado la demostración de la instancia de clase, pero el Demoarray ilista permanece sin inicializar. Entonces, cuando intentamos acceder a ella, la excepción de tiempo de ejecución será arrojada. Esto es lo que estaba sucediendo en mi caso. En la primera respuesta del AJAX, estaba estableciendo la matriz observable a NULL I.E. Sin inicializarlo y luego, en la próxima respuesta AJAX, estaba tratando de acceder a ella.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top