Search code examples
javascriptangularjsng-optionsangular-strapangular-filters

Filter will not work with AngularStrap bs-select and ng-options


I'm attempting to filter the list of available options in a bs-select dropdown list using the ng-options directive per AngularStrap's specifications. I'm simply using their example like so.

HTML:

<button type="button" class="btn btn-default btn-sm" ng-model="selectedIcon" 
    data-html="1"
    data-multiple="1" 
    ng-options="icon.value as icon.label for icon in icons | filter:iconSearch"
    bs-select>
    Action <span class="caret"></span>
</button>
<input type="text" class="form-control input-sm" ng-model="iconSearch" />

Controller (index.js):

$scope.selectedIcons = [];
$scope.icons = [
    {"value":"Gear","label":"<i class=\"fa fa-gear\"></i> Gear"},
    {"value":"Globe","label":"<i class=\"fa fa-globe\"></i> Globe"},
    {"value":"Heart","label":"<i class=\"fa fa-heart\"></i> Heart"},
    {"value":"Camera","label":"<i class=\"fa fa-camera\"></i> Camera"}
];

Problem When I begin typing in the input box (i.e. iconSearch begins to change), the list of available options in the AngularStrap drop-down does not change. If I "hardcode" the filter in ng-options to read ... | filter: 'Gear' it will work just fine on page load.

If I add the following code to the view, I can see that the array of icons is being filtered correctly.

<pre>{{icons | filter:iconSearch | json}}</pre>

Question

  1. Is it even possible to filter the options array dynamically and have bs-select respond accordingly?
  2. If so, how? If not, how can this be altered to work?

Solution

  • It appears that filter does not get evaluated to generate the option list. You could instead do the filtering in the controller.

    In your controller:

      $scope.getIcons = function() {
         return filterFilter(icons, $scope.iconSearch);
      }
    

    In your view:

    <button type="button" class="btn btn-default btn-sm" ng-model="selectedIcon" 
       data-html="1" data-multiple="1" 
       ng-options="icon.value as icon.label for icon in getIcons()" bs-select>
            Action <span class="caret"></span>
     </button>
     <input type="text" class="form-control input-sm" ng-model="iconSearch.value" />
    

    angular.module('app', ['mgcrea.ngStrap', 'ngSanitize']).controller('ctrl', function($scope, filterFilter) {
    
      $scope.selectedIcons = [];
      
      var icons = [{
        "value": "Gear",
        "label": "<i class=\"fa fa-gear\"></i> Gear"
      }, {
        "value": "Globe",
        "label": "<i class=\"fa fa-globe\"></i> Globe"
      }, {
        "value": "Heart",
        "label": "<i class=\"fa fa-heart\"></i> Heart"
      }, {
        "value": "Camera",
        "label": "<i class=\"fa fa-camera\"></i> Camera"
      }];
    
      $scope.getIcons = function() {
         return filterFilter(icons, $scope.iconSearch);
      }
    
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-sanitize.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.5/angular-strap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.5/angular-strap.tpl.min.js"></script>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <div ng-app="app" ng-controller="ctrl">
      <button type="button" class="btn btn-default btn-sm" ng-model="selectedIcon" data-html="1" data-multiple="1" ng-options="icon.value as icon.label for icon in getIcons()" bs-select>
        Action <span class="caret"></span>
      </button>
      <input type="text" class="form-control input-sm" ng-model="iconSearch.value" />
     
    </div>