2016-07-01 15 views
2

Ich habe einige Probleme beim Filtern eines verschachtelten Arrays mit Knockout.Nach Eigenschaften des verschachtelten Arrays filtern - Knockout

Ich möchte in der Lage sein, das Array nach "Tag-Namen" sowie "Name" zu filtern.

. Geben Sie 'whal' ein, und alle Objekte, die ein Tag mit diesem Namen enthalten, werden im Raster gefiltert.

Fiddle: https://jsfiddle.net/king_s/fj9L3wjz/3/

<input data-bind="value: searchQuery, valueUpdate: 'afterkeydown'" /> 

<div data-bind="foreach: filter" class="grid"> 
    <p data-bind="text: name"></p> 
</div> 
(function(){ 
    var ViewModel = function() { 
     var self = this; 
     var obj = { "id": 11, 
      "name": "mouse", 
      "tags": [{ "id": 1, 
       "name": "critter" 
      }] 
     }; 
     var obj2 = { "id": 12, 
      "name": "dolphin", 
      "tags": [{ "id": 2, 
       "name": "fish" 
      }, 
      {"id": 3, 
       "name": "whale" 
      }] 
     }; 
     self.searchQuery = ko.observable(""); 
     self.array = ko.observableArray([obj, obj2]); 
     self.filter = ko.computed(function() { 
      if(!self.searchQuery()) { 
       return self.array(); 
      } else { 
       return ko.utils.arrayFilter(self.array(), function(obj) { 
        return obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1; 
       }); 
      } 
     }); 
    }; 
    ko.applyBindings(new ViewModel()); 
})(); 

Antwort

2

doch einfach eine zweite Prüfung für die Tags hinzufügen:

return ko.utils.arrayFilter(self.array(), function(obj) { 
      var tagsCheck = ko.utils.arrayFilter(obj.tags, function(tag) { 
      return tag['name'].toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1}); 

       return (obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1) || tagsCheck.length; 
       }); 

Überprüfen Sie auch diese fiddle

+0

Perfect thanks! – user3116167

+0

@ Benutzer3116167 NP. Bitte upvote, wenn dir die Antwort gefallen hat. – giannisf

1

Sie werden durch Ihre Unter Objekte wie dieses iterieren:

self.filter = ko.computed(function() { 
    if (!self.searchQuery()) { 
    return self.array(); 
    } else { 
    return ko.utils.arrayFilter(self.array(), function(obj) { 
     var value = obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()); 
     var compensation = 0; // Compensate for how many tags there are 
     obj.tags.forEach(function (tag) { 
     compensation--; 
     value += tag.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()); 
     }) 
     // Final value is greater than -1 + (-1 * number of tags) 
     return value > -1 + compensation; 
    }); 
    } 
}); 

Probieren Sie es hier fiddle

EDIT

ich inspiriert wurde meine Antwort auf die folgende, so sieht es sauberer zu aktualisieren:

self.filter = ko.computed(function() { 
    if (!self.searchQuery()) { 
    return self.array(); 
    } else { 
    return ko.utils.arrayFilter(self.array(), function(obj) { 
     var found = obj.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1; 
     obj.tags.forEach(function(tag) { 
     if (tag.name.toLowerCase().indexOf(self.searchQuery().toLowerCase()) > -1) { 
      found = true; 
     } 
     }); 
     return found; 
    }); 
    } 
}); 

Versuchen Sie es hier fiddle

+0

Sie sind schnell: D – giannisf

+1

Sie sind eine sehr nahe Sekunde, und ich mag Ihre Antwort, auch wenn ich es nicht verstehe lol –

+1

Nevermind, ich habe es. Ich mag das. Meine war schnell, weil es nicht so kondensiert war wie deine. Lol –

0

Ich habe eine KO filters extender eine Weile ag gemacht o was bei diesen Jobs hilft. Es erzeugt eine filtered Eigenschaft auf dem ObservableArray und ermöglicht eine flexible Kumulation von Filtern.

in Ihrem HTML würden Sie tun:

<div data-bind="foreach: array.filtered" class="grid"> 

Und Ihre JS wäre:

self.array = ko.observableArray([obj, obj2]).extend({filters: { 
    search: function(obj) { 
    var query  = self.searchQuery().toLowerCase(), 
     nameMatch = obj.name.toLowerCase().match(query), 
     tagMatch = false; 
    obj.tags.forEach(function(tag, i) { 
     if (tag.name.toLowerCase().match(query)) 
     tagMatch = true; 
    }); 
    return nameMatch || tagMatch; 
    } 
}});  

self.array.toggleFilter('search', true); 

Siehe updated fiddle.

Verwandte Themen