Abernathy Beardevil Abernathy Beardevil - 1 year ago 53
Javascript Question

AngularJS - How should I handle multiple dynamic dropdowns to filter a list?

I'm very new to AngularJS (and somewhat new to Javascript in general) so I'm not sure if I'm even looking at this issue the right way.

I'm getting data from Amazon's Product Advertising API. I'm trying to account for different variations of an item and allow the user to select their preferred variation with dropdowns for the "variation dimensions" which are basically just ways in which the variations differ (size, color, etc)

I don't know in advance what these dimensions will be, so in my JSON data that I get from the server I have an array of all possible items (an array of all valid combinations of these dimensions), an array of dimension names and an array of dimension values.

possible_items = [{'size': 5, 'color': 'red'}, {'size': 5, 'color': 'blue'}];
variation_dimensions = ['size', 'color'];
variation_values['size'] = [5];
variation_values['color'] = ['red', 'blue'];

Currently I'm doing this:

<div class="detailsSelect" ng-repeat="dim in variation_dimensions">
<select class="form-control variation-dropdown">
<option ng-repeat="value in item.variation_values[dim]">{{ value }}</option>

This creates the correct number of selects with the correct values.

How can I use Angular to keep track of what selects were created and use their values to filter the list of possible items?

Answer Source

First of all, in selects you can use ng-options instead of ng-repeat:

<select class="form-control variation-dropdown" 
        ng-options="value for value in item.variation_values[dim]"></select>

Then you need to add ng-model to store what's been selected, and ng-change to apply the selection to your filters:

<select class="form-control variation-dropdown" 
        ng-options="value for value in item.variation_values[dim]" 

In your controller:

$scope.selection = {};  // At the top, just to initialise $scope.selection as a key/value store
$scope.filteredItems= possible_items; // Initially just display everything

$scope.updateFilters = function() {
  for (var dim in $scope.selection) {
    $scope.filteredItems= $scope.filteredItems.filter(function(item) {
      return item[dim]==$scope.selection[dim];

Then you just need to add another section in your html to display the contents of filteredItems.