简体   繁体   中英

Filter ng-repeat based on user selection

I am currently working on a music catalog and trying to implement functionality to allow user to filter the catalog from a list of artists and genres

The list:

    <ul class="artists">
        <li class="title">
            <h5>Artists</h5>
            <ul class="sub-menu">
                <li ng-repeat="artist in music | orderBy:'-views'">
                    <p ng-click="select(artist.artist)">{{artist.artist}}</p>
                </li>
            </ul>
        </li>
    </ul>

I have tried to build a custom filter but couldn't quite grasp the concept, what I managed to do - was get the value from the chosen selection

    // value from ng-click
    $scope.select = function(value){
        filterBy = value;
    }

I know i can add in filter: the ng-repeat by adding

ng-repeat="artist in music | filter: {artist:'artistName' | orderBy:'-views'"}

but how do i change the artist: 'value' to what ever use selects from a list

this is the main area i am trying to filter

    <div class="item" ng-repeat="artist in music | orderBy:'-views'"> 
        <div class="img">
            <img ng-src="{{artist.image}}"/>
        </div>
        <div class="info">
            <h6>{{artist.artist}}</h6>
            <p>{{artist.songName}}</p>
        </div>
    </div>

When the view loads all items should show and then if user wants can select artist or genre from a list to filter to that result. My idea was to maybe place the custom filter function inside the click function, so when user selects from list the value from the click function could be parse into the custom filter and update the filter with correct value. But, I couldn't implement this.

I am quite new to angular.js so if i didn't quite explain it correctly here is a JSfiddle replicating my project.

http://jsfiddle.net/0n2qptg6/5/

Thanks in advance for any help, suggestions, criticisms

One option would be to have a filter object and update it when you click on the different elements. Of course using the filter in the ng-repeat tag.

<div class="item" ng-repeat="artist in music | filter:filteredBy | orderBy:'-views'">

also change the methods to the following

$scope.selectArtist = function(value){
   //pass from ng-click
    $scope.filteredBy.artist = value;
}

$scope.selectGenre = function(value){
    //pass from ng-click
    $scope.filteredBy.genre = value;
}

Check the updated fiddle for an example

http://jsfiddle.net/0n2qptg6/6/

Of course you can try to optimize it a bit if you want, but this should work

Demo

You need to assign the filter to $scope, so that it can be used as a filter for your music album list:

$scope.selectArtist = function(value){
    //pass from ng-click
    $scope.filterByArtist = value;
    alert(filterBy);
}

$scope.selectGenre = function(value){
    //pass from ng-click
    $scope.filterByGenre = value;
    alert(filterBy);
}

Then, apply the filter to your music album list:

<div class="item" ng-repeat="artist in music | 
   filter:{ artist: filterByArtist, genre: filterByGenre } |
   orderBy:'-views'">

First of all filter parameters are bindable. This means that you could do something like this.

ng-repeat="artist in music | filter: {artist: path.to.artistSerachTerm | orderBy:'-views'"} .

Here is an example using a text input & a select list as filters. But you could extend the idea to be checkbox lists as well as a select dropdown.

 var app = angular.module('main', []); app.filter('unique', function() { return function (arr, field) { var o = {}, i, l = arr.length, r = []; for(i=0; i<l;i+=1) { o[arr[i][field]] = arr[i]; } for(i in o) { r.push(o[i]); } return r; }; }); app.controller('MainCtrl', function($scope, $http, $filter) { $scope.music = [ { "artist": "noisia", "songName": "machine gun", "genre": "Drum and Bass", "views": "19" }, { "artist": "etnik", "songName": "n7", "genre": "Techno", "views": "30" }, { "artist": "Jack U", "songName": "To U", "genre": "RnB", "image": "images/cover_3.jpg", "views": "32" }, { "artist": "Makonnen", "songName": "Tuesday", "genre": "Electronic", "image": "images/cover_4.jpg", "views": "72" }, { "artist": "Dillon Francis", "songName": "When We Were Young", "image": "images/cover_5.jpg", "views": "54" }, { "artist": "Justice", "songName": "Stress", "image": "images/cover_6.jpg", "views": "93" } ]; $scope.filteredBy = { artist: '', genre: '' }; $scope.clear = function() { $scope.filteredBy.artist = ''; $scope.filteredBy.genre = ''; } }); 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script> <div ng-app="main" ng-controller="MainCtrl"> <div class="nav"> <p> <label for="byArtistInput">Choose Artist:</label> <input id="byArtistInput" type="text" ng-model="filteredBy.artist" /> <label for="byGenreInput">Choose genre:</label> <select id="byGenreInput" ng-model="filteredBy.genre" ng-options="song.genre as song.genre for song in music | unique: 'genre'"></select> <button type="button" ng-click="clear()">clear</button> </p> </div> <div class="clear"></div> <div class="content"> <div class="item" ng-repeat="artist in music | filter:filteredBy | orderBy:'-views'"> <div class="border"> <!-- | filter: {artist:'etnik'} --> <div class="img"></div> <div class="sub-info"> <h4>{{artist.artist}}</h4> <p>{{artist.songName}}</p> </div> </div> </div> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM