2011-12-29 14 views
33

Estoy trabajando a través del ejemplo del complemento de mapeo en el sitio web de Knockoutjs.Agregando propiedades al modelo de vista creado usando el plugin de mapeo Knockout JS

Este es el ejemplo de datos.

Knockout JS Mapping Plugin

var data = { 
    name: 'Scott', 
    children: [ 
     { id : 1, name : 'Alice' } 
    ] 
} 

El ejemplo muestra cómo reemplazar la asignación para uno de los niños pero ¿cómo altera el mapeo para el objeto base.

Si, por ejemplo, quisiera agregar una propiedad de "FavouriteChild" a Scott, ¿cómo lo haré?

Supongo que necesito usar la función de creación en la asignación base, pero no puedo encontrar un ejemplo de la sintaxis en ninguna parte.

var myChildModel = function(data) { 
    ko.mapping.fromJS(data, {}, this); 

    this.nameLength = ko.computed(function() { 
     return this.name().length; 
    }, this); 
} 

var mapping = { 
    'children': { 
     create: function(options) { 
      return new myChildModel(options.data); 
     } 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

EDIT: De la respuesta aceptada a continuación he encontrado que esto funcione

<span data-bind='text: AdditionalProperty'> 

El código nocaut

var mapping = { 
    create: function (options) { 
     //customize at the root level. 
     var innerModel = ko.mapping.fromJS(options.data); 

     innerModel.AdditionalProperty = 'Hello World'; 

     return innerModel; 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

//use this as our model bindings 
ko.applyBindings(viewModel); 

Respuesta

23

Es necesario utilizar un método create en el propio objeto de asignación como:

var mapping = { 
    //customize at the root level. 
    create: function(options) { 
    //first map the vm like normal 
    var vm = ko.mapping.fromJS(options.data); 

    //now manipulate the returned vm in any way that you like 
    vm.someProperty = "test"; 

    vm.someComputed = ko.computed(function() { 
      return vm.first() + " " + vm.last(); 
    }); 

    //return our vm that has been mapped and tweaked 
    return vm; 
    } 
}; 
+6

¿Qué hay de explicar cómo, que crean con una función de vacío no demuestra nada acerca del acceso a la raíz nivel y agregando a esto. –

+0

actualizó la función para mostrar cómo mapearía y manipularía el resultado antes de devolverlo. –

+0

Sé que esta es una pregunta muy antigua, pero habiéndolo descubierto quería hacer una sugerencia. El ejemplo de código para usar la devolución de llamada de creación al mapear (en el sitio de KnockoutJs) no explica que el método de creación está en el objeto de mapeo. Ryan, si puedes, le pediría al propietario del sitio que reemplace su muestra de código con la suya anterior. –

13

Aquí es una continuación a esta respuesta basado en la solución de RP Niemeyer

Esta respuesta aquí se basa en la solución anterior y de su blog - Gracias por eso! Pensé que debería agregar algunos detalles porque aborda cuándo la matriz no es un objeto de primer nivel.

var data = { 
person: { 
     children: [{ id: 1, firstName: 'Scot', lastName: 'Weise'}] 
    } 
}; 

var mapping = { 
    'children': { 
     create: function(options) { 
      return (new (function() { 
       // setup the computed binding for some reason I had 
       // to use ko.dependentObservable instead of ko.computed 
       // or errors showed up. 
       this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, { }, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    // Create view model and map the data object to the model. 
    var viewModel = ko.mapping.fromJS(data, {}); 

    // update the viewModel with the mapping object that contains 
    // some a computed property(s) 
    viewModel.person = ko.mapping.fromJS(viewModel.person, mapping); 
    ko.applyBindings(viewModel); 

Tenga en cuenta que la persona es el objeto de primer nivel y children es una propiedad secundaria de esa persona. La línea viewModel.person = ko.mapping.fromJS (viewModel.person, mapping) no fue intérprete para mí al principio.

Y aquí es una ligera variación

El objeto persona es un observable que se añade o se actualiza después de que se creó originalmente a partir de los datos JSON del servidor.

var viewModel = {}; 
$(document).ready(function() { 
    var person = getPerson(); 

    // selected person is added to the viewModel 
    viewModel.selectedPerson = ko.observable(person); 
    ko.applyBindings(viewModel); 
}); 

function getPerson() { 
// you would probably pass this into the function as a parameter. 
var person = 
    { 
     name: 'jim', 
     children: [{ id: 1, firstName: 'jane', lastName: 'bob'}] 
    }; 

    var mapping = { 
     'children': { 
      create: function (options) { 
       return (new (function() { 
        // setup the computed binding 
        this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, {}, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    var result = ko.mapping.fromJS(person, mapping); 
    return result; 
} 

Parte del código de enlace en el html

En última instancia, tendrá que poner a un cierto uso en algún momento como éste:

<div data-bind="foreach:viewModel.selectedPerson().children"> 
    <span data-bind="text:fullName"></span> 
</div> 

Gracias por su ayuda! No podría haber llegado tan lejos sin tu publicación en el blog.

3

Tenga en cuenta que para definir los observables calculados adicionales en un niño que tendrá que pasar otro conjunto de opciones de asignación

var mapping = { 
    create: function(options) { 
    //customize at the root level. 

    var mapping2 = { 
     'children': { 
     create: function(options) { 
      //customize children also 

     } 
     } 
    } 

    //call ko.mapping.fromJS on the options.data as well with further customization 
    ko.mapping.fromJS(options.data, mapping2, this); 
    } 
}; 
+1

Llegué aquí buscando cómo mapear propiedades anidadas y en mi humilde opinión este fue el ejemplo más claro. Si incluía una muestra de viewModel, sería una solución completa para mí. –

0

Otro ejemplo sobre la base de los ejemplos proporcionados por Jason y RP Niemeyer.

data es lo que obtenemos después de una consulta ajax, en el que añadimos dos observables anidados (viewModel.weekly.selectedWeek y viewModel.monthly.selectedMonth):

var data = { 
     "date": "2017-03-28", 
     "weekly": { 
      "weeks": [ 
       { 
        "id": "201701", 
        "label": "Week 1" 
       }, 
       { 
        "id": "201702", 
        "label": "Week 2" 
       } 
      ] 
     }, 
     "monthly": { 
      "months": [ 
       { 
        "id": "201701", 
        "label": "01/2017" 
       }, 
       { 
        "id": "201702", 
        "label": "02/2017" 
       } 
      ] 
     } 
    } 

    var viewModelMapping = { 
     create: function (options) { 
      return (new (function() { 
       // viewModel root level 
       var mapping2 = { 
        'weekly': { 
         create: function (options) { 
          // viewModel.weekly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedWeek = ko.observable(); 
           return model; 
          }; 
         } 
        }, 
        'monthly': { 
         create: function (options) { 
          // viewModel.monthly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedMonth = ko.observable(); 
           return model; 
          }; 
         } 
        } 
       }; 

       ko.mapping.fromJS(options.data, mapping2, this); 
      })()); 
     } 
    }; 


    var viewModel = ko.mapping.fromJS(data, viewModelMapping); 
    ko.applyBindings(viewModel); 
Cuestiones relacionadas