knockout for data javascript knockout.js filter observable

javascript - data - knockout js for



Knockout Filtering en Matriz Observable (3)

Es posible que desee echar un vistazo al plugin Proyecciones Knockout del autor del knockout original. Tiene ventajas de rendimiento en escenarios con grandes colecciones . Ver blogpost para más detalles.

self.filterProducts = self.products.filter(function(prod) { return !self.currentFilter() || prod.genre == self.currentFilter(); });

Empecé a aprender Knockout y estoy teniendo problemas para filtrar una matriz observable al hacer clic en un botón y mostrar los resultados.

Este es mi modelo:

function Product(data) { this.id = data.id; this.name = data.name; this.price = data.price; this.description = data.desc; this.image = data.image; this.genre = data.genre; this.show = data.show; this.offer_desc = data.offer_desc; this.offer_id = data.offer_id; } function ProductModel() { var self = this; self.products = ko.observableArray([]); $.getJSON(''../PHP/Utilities.php?json=true'', function(json) { var mappedProducts = $.map(json, function(item) { return new Product(item) }); self.products(mappedProducts); }); self.filterProducts = ko.computed(function(genre) { if(typeof genre === ''undefined'') { return self.products(); //initial load when no genre filter is specified } else { return ko.utils.arrayFilter(self.products(), function(prod) { return prod.genre = genre; }); } }); } ko.applyBindings(new ProductModel());

Este es el html:

<div data-bind="foreach: filterProducts"> <div class="row"> <div class="col-md-2"> <img data-bind="attr:{src: ''../images/'' + image, alt: name}" /> </div> <div class="col-md-2" data-bind="text: name"></div> <div class="col-md-1" data-bind="text: price"></div> <div class="col-md-3" data-bind="text: description"></div> <div class="col-md-1" data-bind=''text: offer_id''> <div class="col-md-2" data-bind="text: genre"></div> <div class="col-md-1" data-bind="text: show"></div> </div> </div>

Tampoco estoy seguro de cómo enlazar una función de clic para filtrar los productos en el género. Pensé algo como esto ... pero no funciona

<button data-bind="click: filter(''1'')"> Filter </button> self.filter = function(genre) { self.filterProducts(genre); }


No puede tener una función con parámetros dentro de ko.computed .

Lo que necesita es almacenar el filtro actual en una nueva propiedad y usarlo en su computador

function ProductModel() { var self = this; self.products = ko.observableArray([]); self.currentFilter = ko.observable(); // property to store the filter //... self.filterProducts = ko.computed(function() { if(!self.currentFilter()) { return self.products(); } else { return ko.utils.arrayFilter(self.products(), function(prod) { return prod.genre == self.currentFilter(); }); } }); }

Y en su controlador de click simplemente configure el filtro actual:

<button data-bind="click: function() { filter(''1'') }"> Filter </button> self.filter = function(genre) { self.currentFilter(genre); }

Demo JSFiddle

Tenga en cuenta que la function() { } necesaria si desea pasar argumentos adicionales a en el enlace de click (ver también en la documentation ), de lo contrario Knockout ejecutaría su función cuando analiza el enlace y no cuando hace clic en el botón.


Primero lo malinterpretas / usas para los computed Observables . De la documentación de KnockoutJS :

Estas son funciones que dependen de uno o más observables, y se actualizarán automáticamente cada vez que cambie alguna de estas dependencias.

Su filterProducts computable observable Los filterProducts dependen de los products matriz observables que no cambia , solo lee su valor. Por lo tanto, no hay nada que notificar a filterProducts para que se vuelva a evaluar.

Entonces, ¿cuál sería la solución rápida y simple?

  1. Define un nuevo objeto observable filterProducts que dependerán tus filterProducts .
  2. Cambie los productos de filterProducts para que compruebe el valor de filteredGenre y, en función de ello, devuelva los productos filtrados.
  3. Cambie la función de filter para que cuando obtenga un nuevo genre cambie filteredGenre que daría como resultado una reevaluación de los filterProducts calculados filterProducts

Espero que entiendas la idea.