Search code examples
javascriptangularjsangular-filters

Unique filtered select list in angular only returning single item in data set


I have a data set that I'm trying to filter with a select list in Angular. The select list is populated with entries from the data, and I'm filtering that using the angular-filter to give me just the 'uniques'.

The problem is that because the select list is being filtered by uniques, if I use the select list to filter the data set, it's only returning one item back and not all of them that match that criteria.

I'm also unsure of how to have the filter lists work together so each list will whittle down the data set further.

And finally, I'm unsure of how to have the data reset when the select list item is set back to the defaults.

http://plnkr.co/edit/5s1BN7?p=preview

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

app.controller('MainCtrl', function($scope, $anchorScroll, $location) {

  $scope.cart = [];

  $scope.addToCart = function(index) {
    $scope.cart.push(index);

    $scope.cartCount = $scope.cart.length;
  }



  $scope.activeRow = function(index) {
    $scope.selectedRow = index;

    $location.hash();
    $anchorScroll('anchor-' + index);

  }



  $scope.gotoAnchor = function(x) {
    var newHash = 'anchor' + x;


  }

  $scope.dataObject = [{
      "Number": "001",
      "Status": "NCB",
      "Compound": "CD19A"
    }, {
      "Number": "002",
      "Status": "NCA",
      "Compound": "CD19B"
    }, {
      "Number": "003",
      "Status": "NCA",
      "Compound": "CD33C"
    }, {
      "Number": "001",
      "Status": "NCA",
      "Compound": "CD33D"
    }, {
      "Number": "002",
      "Status": "NCB",
      "Compound": "CD33E"
    }, {
      "Number": "003",
      "Status": "NCB",
      "Compound": "CD20F"
    }, {
      "Number": "001",
      "Status": "NCB",
      "Compound": "CD20G"
    }, {
      "Number": "002",
      "Status": "NCC",
      "Compound": "CD20H"
    }, {
      "Number": "003",
      "Status": "NCC",
      "Compound": "CD33I"
    }, {
      "Number": "001",
      "Status": "NCC",
      "Compound": "CD33J"
    }

  ];


});
/* Put your css in here */

body {
  background: #eee;
}
div.cart {
  display: block;
  height: 70px;
  background: silver;
  margin-left: 20px;
  width: 200px;
  padding: 5px 10px;
  margin-bottom: 20px;
  margin-top: 20px;
}
.cart h1 {
  color: #fff;
  line-height: 20px;
}
.item-list-wrapper {
  height: 300px;
  width: 740px;
  border: 1px solid #ddd;
  overflow-y: scroll;
  margin-left: 20px;
}
.item-list {
  height: 70px;
  width: 100%;
  margin-bottom: 10px;
  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
  border: 1px solid #fff;
  background: #efefe4;
}
li {
  display: inline-block;
  list-style: none;
  padding: 0 40px 40px 40px;
  font-size: 24px;
}
.open {
  height: 300px;
  background: #fff;
}
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <link data-require="bootstrap@*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.4.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js" data-semver="1.4.7"></script>
  <script data-require="angular.js@1.4.x" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular-messages.js"></script>
  <script src="angular-filter.min.js"></script>
  <script src="app.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.7/angular-filter.js"></script>


</head>

<body ng-controller="MainCtrl">
  <div ng-view=""></div>

  <div>
    <h2>Filter results</h2>

    <select name="some_name" id="some_name" onchange="" class="form-control" ng-model="selectNumber" ng-options="data.Number for data in dataObject | unique: 'Number' ">
      <option value="">Select Number</option>
    </select>
    <select name="some_name" id="some_name" onchange="" class="form-control" ng-model="selectStatus" ng-options="data.Status for data in dataObject | unique: 'Status' ">
      <option value="">Select Status</option>
    </select>
    <select name="some_name" id="some_name" onchange="" class="form-control" ng-model="selectCompound" ng-options="data.Compound for data in dataObject | unique: 'Compound' ">
      <option value="">Select Compound</option>
    </select>


  </div>



  <div class="cart">
    <h1>Cart: {{cartCount}}</h1>
  </div>


  <div class="item-list-wrapper">
    <div class="item-list" ng-repeat="data in dataObject | filter: selectNumber | filter: selectStatus | filter: selectCompound" ng-click="activeRow($index)" ng-class="{'open':$index == selectedRow}">
      <a id="anchor-{{$index}}"></a>
      <ul>
        <li>{{data.Number}}</li>
        <li>{{data.Status}}</li>
        <li>{{data.Compound}}</li>
        <li>
          <a href="" ng-click="addToCart()">Add to Cart</a>
        </li>
      </ul>
    </div>
  </div>
  <!--item-list-wrapper -->


</body>

</html>


Solution

  • In the model, select the property value instead of the full object:

    ng-options="data.Number as data.Number for data in dataObject | unique: 'Number' "
    

    Also, as you are using angular-filter, replace filter with filterBy:

    filterBy: ['Number']: selectNumber
    

    The reason of this replacement is that it handles correctly the case when the selected value is resetted to an empty string.

    See updated plunkr