<!DOCTYPE html>
<html ng-app="myApp">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="//maxcdn.bootstrapcdn.com/bootswatch/3.0.3/slate/bootstrap.min.css" rel="stylesheet" type="text/css"/>
    <link href="//moonstorm.github.io/trNgGrid/release/trNgGrid.min.css" rel="stylesheet" type="text/css"/>

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular-route.min.js"></script>
    <script src="//moonstorm.github.io/trNgGrid/release/trNgGrid.min.js"></script>
    <script src="trNgDropdownFilter.js"></script>
    <script src="script.js"></script>
  </head>
  <body class="container" ng-controller="MainCtrl">
    
    <h1>TrNgGrid Column Dropdown Filter Example</h1>

    <table tr-ng-grid="" items="myItems">
      <thead>
        <tr>
          <th field-name="city" display-name="City"></th>
          <th field-name="state" display-name="State"><dropdown-filter /></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td field-name="city"></td>
          <td field-name="state"></td>
        </tr>
      </tbody>
    </table>

  </body>
</html>
angular
    .module('myApp', ['trNgGrid'])
    .controller("MainCtrl", ["$scope", function ($scope) {
    
        $scope.myItems = [
            { city: "New York",     state: "NY" },
            { city: "Buffalo",      state: "NY" },
            { city: "Chicago",      state: "IL" },
            { city: "San Diego",    state: "CA" },
            { city: "San Fransico", state: "CA" },
            { city: "Los Angelos",  state: "CA" },
            { city: "Las Vegas",    state: "NV" },
            { city: "Albany",       state: "NY" },
            { city: "Reno",         state: "NV" },            
            { city: "Denver",       state: "CO" }
        ];
            
    }]);
<div>
    <div class="tr-ng-title" ng-class="{'tr-ng-sort': gridOptions.enableSorting}" ng-click="!((gridOptions.enableSorting && columnOptions.enableSorting!==false)||columnOptions.enableSorting) || toggleSorting(columnOptions.fieldName)">
        <div ng-show="(gridOptions.enableSorting && columnOptions.enableSorting!==false)||columnOptions.enableSorting"
             ng-class="{'tr-ng-sort-active text-info': gridOptions.orderBy==columnOptions.fieldName, 'tr-ng-sort-inactive text-muted glyphicon glyphicon-chevron-down': gridOptions.orderBy!=columnOptions.fieldName, 'tr-ng-sort-order-normal glyphicon glyphicon-chevron-up': gridOptions.orderBy==columnOptions.fieldName && !gridOptions.orderByReverse, 'tr-ng-sort-order-reverse glyphicon glyphicon-chevron-down': gridOptions.orderBy==columnOptions.fieldName && gridOptions.orderByReverse}"
             class="tr-ng-sort-inactive text-muted glyphicon glyphicon-chevron-down"></div>
        {{label}}
    </div>
    <div class="tr-ng-column-filter" ng-show="(gridOptions.enableFiltering && columnOptions.enableFiltering !== false) || columnOptions.enableFiltering">
        <select class="form-control input-sm" ng-model="columnOptions.filter">
            <option value="" selected></option>
            <option ng-repeat="item in items">{{item.predicateObject}}</option>
        </select>
    </div>
</div>
angular.module("trNgGrid").directive("dropdownFilter", ["$filter", "$parse", function ($filter, $parse) {

    var templateUrl = "dropdown-filter-tmpl.html";

    return {
        restrict: "E",
        require: "^trNgGrid",
        scope: true,
        templateUrl: templateUrl,
        link: function (scope, element, attr, table) {
            var field = scope.columnOptions.fieldName;
            var label = (angular.isDefined(scope.columnOptions.displayName) && scope.columnOptions.displayName !== null ? scope.columnOptions.displayName : field);

            var collection = angular.copy(table.gridOptions.items);
            collection = $filter("nonBlank")(collection, field);           
            collection = $filter("unique")(collection, field);
            collection = $filter("orderBy")(collection, field);
            
            angular.forEach(collection, function (item) {
                item.predicateObject = $parse(field)(item);
            });

            scope.label = label;
            scope.items = collection;
        }
    };

}]);

angular.module("trNgGrid").filter("nonBlank", function ($parse) {

    return function (items, filterOn) {
        var newItems = [];

        if (filterOn === false) {
            return items;
        }

        if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
            angular.forEach(items, function (item) {
                var value = $parse(filterOn)(item);

                if (value !== "" && angular.isDefined(value)) {
                    newItems.push(item);
                }
            });
        }

        return newItems;
    };
});

angular.module("trNgGrid").filter("unique", function ($parse) {

    return function (items, filterOn) {
        var newItems = [];

        if (filterOn === false) {
            return items;
        }

        if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {

            var extractValueToCompare = function (item) {
                var result = item;

                if (angular.isObject(item) && angular.isString(filterOn)) {
                    return $parse(filterOn)(item);
                }

                return result;
            };

            angular.forEach(items, function (item) {
                var isDuplicate = false;
                var value = $parse(filterOn)(item);

                for (var i = 0; i < newItems.length; i++) {
                    if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(value))) {
                        isDuplicate = true;
                        break;
                    }
                }

                if (!isDuplicate) {
                    newItems.push(item);
                }

            });
        }

        return newItems;
    };
});