简体   繁体   中英

Nesting ng-repeat on one element for filtering

I have a page which is built up of tiles (imagine a list of div's with a thumbnail and a title) - each 'tile' can have several tags attributed to them..

Eg:

  • tile 1 has the following tags: foo , bar , baz , quz
  • tile 2 has the following tags: foo , bar , baz
  • tile 3 has the following tags: bar , baz
  • tile 4 has the following tags: baz , quz .. and so on..

At the top of the page there is a simple filter menu - with each tag clickable in a list.

When clicking a tag in the filter menu eg foo , hide any tile which hasn't got the foo tag attributed to it. In this case, tiles 3 and 4 will be removed from view.

Each tile has the following template, but I need to extend this to incorporate the tag filtering...

<div ng-repeat="tile in tiles" class="col-md-2" ng-show="showFiles.filters[tile.filetype]">
  <div class="sc-file-container">
    <h3>{{tile.name}}</h3> // add image here too
  </div>
</div>

Very new to the angular way, but basically in order to use ng-hide/ng-show I've been creating arrays in the controller $scope - see above, so when showFiles.filters['tile.filetype'] is set true (by an onclick via a directive on another filter menu for example), the tile will show or hide..

Question: As there are potentially several tags attributed to each tile - what would be the best way to utilise ng-show in the above example? How can I iterate over the tags array - but keep within the <div> ? Is it possible to have 2 ng-repeat 's on one element or would I have to create several dummy <div> wrappers, just to apply for example ng-show="filterByTag['foo']" to the tile

Example of json:

"tiles" : {
..
.
"filetype" : "pdf",
"name" : "this is tile 1!",
..

 "tags":[  
  {  
    "id":1,
    "name":"foo"
  },
  {  
    "id":2,
    "name":"bar"
  },
  {  
    "id":3,
    "name":"baz"
  }
  ..
 ]
 ..
}

Better way to do this in angular is filter your tiles array based on selected tag filter.

<div ng-repeat="tile in filteredTiles" class="col-md-2">
   <div class="sc-file-container">
      <h3>{{tile.name}}</h3> // add image here too
   </div>
</div>

<script>
     var filteredTiles = [];
     // Logic to filter tiles based on selected tag in filter

</script>

What you want to do is i would say a bit not correct. There are filters available in the angular to filter out the data but for this you need to update the model ng-model . I guess you should do it like this:

Markup:

<div ng-controller="MainCtrl">
  <button id='foo' ng-model='clickedItem.item' ng-model-options="{ updateOn: 'click' }" ng-btn>Foo</button>
  <button id='bar' ng-model='clickedItem.item' ng-model-options="{ updateOn: 'click' }" ng-btn>Bar</button>
  <button id='baz' ng-model='clickedItem.item' ng-model-options="{ updateOn: 'click' }" ng-btn>Baz</button>
  <div ng-repeat="tile in tiles | filter:clickedItem.item" class="col-md-2">
    <div class="sc-file-container">
      <h3>{{tile.name}}</h3>
    </div>
  </div>
</div>

In the above markup you can see that we have three buttons with different ids like foo, bar, baz and those buttons also have two directives ng-model and ng-model-options and below that where you have ng-repeat you have to have a filter as you can see in the markup as ng-repeat="tile in tiles | filter:clickedItem.item" .

Now whenever model updates you can see the difference. That only happens when you use ng-model-options="{updateOn:'click'}" which says update the model whenever click happens on the button.

angularjs code:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) { // controller
  $scope.clickedItem = {}; // holds the clicked button's id
  $scope.tiles = [{name: 'foo'}, {name: 'bar'}, {name: 'baz'}];
}).directive('ngBtn', function(){
  return {
    link:function(scope, elem, attrs){
      angular.element(elem).on('click', function(){ // click on button
        scope.clickedItem.item = this.id; // update clickedItem
      });
    }
  };
});

See the demo @ plnkr.

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