observablearray knockout data knockout.js knockout-mapping-plugin

knockout.js - data - KnockoutJS: Agregar propiedades y funciones observables a objetos en una asignaciĆ³n ObservableArray generada



ko observablearray (3)

Esto es lo que se me ocurrió usar las respuestas de Ryan y tú ... parece funcionar. Por favor, deje un comentario, ya que soy nuevo en Knockout y tengo curiosidad, si este es un buen enfoque.

JS:

$(function() { $.get("users/getUsers", function(r){ var vm = ko.mapping.fromJS(r, { users: { create: function(user){ var methods = { toggleIsActive: function(u){u.IsActive(!u.IsActive());}, foo: function(u){console.log(u);}, bar: function(u){/*whatever*/}, } return $.extend(ko.mapping.fromJS(user.data), methods); } } }); ko.applyBindings(vm); }, ''json''); });

DOM:

<!-- ko foreach: users --> <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a> <!-- /ko -->

Soy nuevo en KnockoutJS , y estoy atascado tratando de agregar propiedades y métodos adicionales a los objetos generados en el ko.observableArray() creado por el complemento de mapping .


Aquí es donde estoy haciendo:

  • Tengo una matriz de Users JSON
  • He creado el ko.observableArray() con el complemento de mapeo
  • Tengo una plantilla que crea una fila de tabla para cada User , hasta ahora bien: o)


Esto es lo que estoy tratando de hacer:

Cada User tiene una propiedad llamada ''IsActive'' : me gustaría data-bind un evento de clic a un método en cada objeto de User que alterna esta propiedad ''IsActive'' .

Esta pregunta parecía prometedora , pero me parece una duplicación innecesaria tener que declarar todo el Modelo de Vista en JS (¡a menos que sea así como tengo que hacerlo!) ¿Es posible simplemente extender el objeto generado?

Pensé más en estas líneas , donde hay una forma de declarar propiedades o métodos adicionales, y hacer que extiendan la mapping objetos generados, pero este artículo trata sobre objetos individuales en lugar de extender objetos en una matriz generada.


Aquí está el código: http://jsfiddle.net/yZkSf/2/ (aún no funciona en el violín de JS, pero seguiré jugando con él y actualizaré este enlace cuando lo haga funcionar).

Gracias por tu ayuda


Hay varias opciones que podrías considerar.

-Uno es usar la devolución de llamada create para controlar cómo se crean los objetos de "usuario". Puede definir los observables usted mismo y agregar una funcionalidad adicional o llamar al complemento de mapeo en el objeto de usuario individual y luego agregar una funcionalidad adicional.

Sería algo como: http://jsfiddle.net/rniemeyer/fkVaK/

-De lo contrario, puede colocar la función "alternar" en su viewModel y luego pasarle el objeto "usuario".

Una buena manera con 1.3, es usar ko.dataFor junto con algo como jQuery live / delegate / on function de delegación de eventos. Sería como: http://jsfiddle.net/rniemeyer/FkjNr/

//unobtrusive event handler $(".toggle").live("click", function() { var user = ko.dataFor(this); if (user) { viewModel.toggleIsActive(user); } });

Si no desea utilizar la delegación de eventos, puede pasar el elemento directamente mediante una función anónima como: http://jsfiddle.net/rniemeyer/GpQtN/

EDITAR: a partir de 2.0, los datos actuales se pasan automáticamente al controlador cuando se usan enlaces de evento / clic, por lo que puede hacer:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>


He encontrado una forma de hacerlo, pero significa recorrer en bucle los objetos generados en la matriz una vez que se han creado. Preferiría una forma de lograr el mismo resultado sin el bucle adicional.

EDITAR: Como sugiere RP Niemeyer en su respuesta! ; o)

De todos modos, una forma de agregar propiedades a un objeto existente es usar jQuery extend () para combinar los objetos.

Primero, declare las propiedades y funciones adicionales en un nuevo objeto:

var userModel = { toggleIsActive: function() { console.log(''toggleIsActive called: before: '' + this.IsActive()); this.IsActive(!this.IsActive()); // todo: save! console.log(''toggleIsActive called: after: '' + this.IsActive()); } }

Luego, después de la llamada ko.mapping.fromJS() , pero antes de la llamada ko.mapping.fromJS() , ko.applyBindings() los objetos en la matriz generada y ko.applyBindings()

viewModel.users = ko.mapping.fromJSON(/* get JSON */); for (var i = 0; i < viewModel.users().length; i++) { $.extend(viewModel.users()[i], userModel); } ko.applyBindings(viewModel);