Grid

The grid directive builds a full-featured grid with a search box, column picker, and filter form. The parent bb-grid directive includes multiple child directives.

Dependencies


Grid settings

  • bb-grid — Creates a full-featured grid that includes a search box, column picker, and filter form.
    • bb-grid-toolbar — Directive that contains the filter summary and custom content for the grid toolbar. Custom content will be displayed between the add button and the search input.
      • bb-grid-filter-click(Optional.) Specifies a function to be called when the filter button is clicked.
      • bb-grid-search(Optional.) Specifies a function to be called when search text is applied. The callback should have the following arguments:
        • searchText — Search text that has been applied.
      • bb-grid-search-text(Optional.) Specifies search text that users can supply to the grid search box.
      • bb-grid-search-text-changed(Optional.) Specifies a function to be called when search text in the input changes. The callback should have the following arguments:
        • searchText — New search text in the search input.
      • bb-grid-search-placeholder(Optional.) Specifies placeholder text for the grid search box. (Default: Find in this list)
      • bb-grid-toolbar-filter-summary(Optional.) Contains content that will be placed in the filter summary section of the grid toolbar. See the filter module for the bb-filter-summary component which can be placed inside of here.
      • bb-grid-toolbar-sort(Optional.) Contains content that will be placed in the sort section of the grid toolbar. See the sort module for the bb-sort component which can be placed inside of here.
    • bb-grid-filters(Deprecated.) Use the components in the filter module instead. (Optional.) Creates a flyout filter menu within the bb-grid directive.
      • bb-options(Deprecated.) Use the components in the filter module instead. Specifies an object with the following properties for the bb-grid-filters directive.
        • applyFilters(Deprecated.) Use the components in the filter module instead. Specifies a function to be called when users click the button to apply filters. You can set args.filters to pass updated filters to bb-grid.
        • clearFilters(Deprecated.) Use the components in the filter module instead. Specifies a function to be called when users click the button to clear filters. You can set args.filters to pass updated filters to bb-grid.
      • bb-grid-filters-group(Deprecated.) Use the components in the filter module instead. Creates collapsible areas within the bb-grid-filters directive.
        • bb-grid-filters-group-label(Deprecated.) Use the components in the filter module instead. Specifies text labels for the collapsible groups that the bb-grid-filters-group directive creates.
    • bb-grid-filters-summary(Optional.) (Deprecated.) Use the components in the filter module instead. Creates a summary toolbar for applied filters within the bb-grid directive.
      • bb-options(Deprecated.) Use the components in the filter module instead. Specifies an options object for the bb-grid-filters-summary directive.
        • clearFilters(Deprecated.) Use the components in the filter module instead. Specifies a function to be called when users click the button to clear filters. You can set args.filters to pass updated filters to bb-grid.
      • bb-grid-filters-summary-dismissable(Deprecated.) Use the components in the filter module instead. (Optional.) Specifies whether the filter summary can be dismissed. (Default: true)
    • bb-grid-options — Specifies an object with the following properties for the bb-grid directive.
      • columns — An array of available columns. Each column can have the following properties:
        • allow_see_more(Optional.) Indicates whether to include a link for users to view overflow content. To display the link, set this property to true.
        • caption — Specifies a caption to display in the column header and column picker.
        • category(Optional.) Specifies a category for the column. The column picker lets users filter columns by category.
        • center_align(Optional.) Indicates whether to center-align the content in the column. To center-align content, set this property to true. By default, content is left-aligned.
        • controller(Optional.) Specifies the controller function for a templated column to allow cells to perform logic while displaying formatted or complex data. You can use $scope.rowData to access row data from the grid in the column template controller.
        • description(Optional.) Specifies a column description to display in the column picker.
        • exclude_from_search(Optional.) Indicates whether exclude the column from highlighting search text. To prevent the column from highlighting search text, set this property to true.
        • id — Specifies a unique identifier for the column. The options object's selectedColumnIds property references this ID.
        • jsonmap — Specifies the name of the property within the data property that maps to the data in the column.
        • name — Specifies a unique name for the column. If the name value is different than the jsonmap value, then it must not match the value for any properties in the bb-grid-option property's data property.
        • right_align(Optional.) Indicates whether to right-align the content in the column. To right-align content, set this property to true. By default, content is left-aligned.
        • template_url(Optional.) Specifies the URL for a column template to use when displaying formatted or complex data in a cell. To access the properties of the cell data object, use the format data.property_name.
        • title(Optional.) Indicates whether to display the column's content in tooltips. By default, column cells display tooltips because jqGrid places cell content in title attributes. To hide tooltips by not creating title attributes, set this property to false. (Default: true)
        • width_all(Optional.) Sets the default column width (in pixels). To override the default column width for certain screen sizes, you can set breakpoint-specific column widths with the width_xs, width_sm, width_md, and width_lg properties. When columns do not take up the entire the grid, the last column extends beyond its default width to take up the remaining space. (Default: 150px)
        • width_xs(Optional.) Sets the column width for screen sizes less than 768px.
        • width_sm(Optional.) Sets the column width for screen sizes from 768px to 991px.
        • width_md(Optional.) Sets the column width for screen sizes from 992px to 1199px.
        • width_lg(Optional.) Sets the column width for screen sizes greater than 1199px.
      • columnPickerHelpKey(Optional.) Sets the help key for the column picker.
      • columnPickerSubsetLabel(Optional.) Specifies a label for a checkbox to include or exclude a subset of the columns.
      • columnPickerSubsetProperty(Optional.) Specifies a property name of the column that will be used to filter by subset. The property will be set to true if it is a member of the subset.
      • columnPickerSubsetExclude(Optional.) When set to true, instructs the column picker to exclude columns with the columnPickerSubsetProperty set to true when the subset checkbox is selected. When set to false, the column picker includes the columns with the columnPickerSubsetProperty set to true when the subset checkbox is selected. (Default: false)
      • columnPickerOnlySelected(Optional.) When set to true, instructs the column picker to include a checkbox which hides unselected items when checked.
      • data — An array of objects that represents the rows in the grid. Each row should have properties that correspond to the jsonmap properties within the columns property.
      • fixedToolbar(Optional.) Indicates whether to prevent the toolbar and grid headers from scrolling with the window. To prevent them from scrolling, set this property to true. (Default; false)
      • filtersAreActive(Optional.) Indicates whether to highlight the filter button to indicate that the grid is filtered. To highlight the button, set this property to true.
      • filtersOpen(Optional.) Indicates whether to open the flyout filter menu. To open the flyout, set this property to true.
      • getContextMenuItems(Optional.) Specifies a function that allows grid rows to create a context menu based on the function's return value. The function returns an array of objects that represents the items in the dropdown. The objects contain the following properties:
        • id — Specifies a unique string identifier for the dropdown item.
        • title — Specifies the title to display in the dropdown.
        • cmd — Specifies a function to be called when users click the dropdown item. To close the dropdown after calling the function, it should return false.
      • hasInlineFilters(Optional.) Indicates whether to display transcluded content in the bb-grid directive when users click the filter button. To display transcluded content, set this property to true.
      • hasMoreRows(Optional.) Indicates whether to display a button that exposes more rows if the grid does not use pagination. To display the button, set this property to true.
      • hideColPicker(Optional.) Indicates whether to hide the column picker button in the toolbar. To hide the button, set this property to true.
      • hideFilters(Optional.) Indicates whether to hide the filters button in the toolbar. To hide the button, set this property to true.
      • loading(Optional.) When set to true, automatically displays a bbWait component over the grid's data.
      • multiselect(Optional.) Indicates whether to add a multi-select checkbox column to the grid. To add the column, set this property to true.
      • onAddClick(Optional.) Specifies a function to be called when users click the add button in the toolbar. The add button only appears if the onAddClick property specifies a function.
      • onAddClickLabel(Optional.) Specifies tooltip text for the add button.
      • resources(Optional.) Specifies the resource dictionary available in the scope of each columns property's template_url and controller properties.
      • searchText(Deprecated.) Use bb-grid-toolbar with the bb-grid-on-search function instead. The text that users enter in the grid search box. Set by the bb-grid directive.
      • selectedColumnIds — An array of unique identifiers that indicates the visible columns in their display order.
      • sortOptions(Optional.) Specifies options for displaying sort indication in column headers.
        • excludedColumns(Optional.) Specifies an array of the names of columns that users cannot use to sort the grid. Prevents the grid headers from showing sort indication on click when not using bb-grid-toolbar-sort.
        • column — Specifies the name of the column that has been sorted.
        • descending — Indicates whether the sort is in descending order. When set to true the arrow icon in the specified column header will point downwards, otherwise the arrow icon will point upwards.
    • bb-grid-pagination(Optional.) Specifies an object with the following properties to indicate that the grid uses pagination instead of infinite scrolling.
      • currentPage(Optional.) Specifies the current page starting at 1. (Default: 1)
      • itemsPerPage(Optional.) Specifies the number of rows per page to display in the grid. (Default: 5)
      • maxPages(Optional.) Specifies the maximum number of pages to display in the pagination bar. (Default: 5)
      • boundaryLinks(Optional.) Specifies whether or not to show the first and last page numbers with ellipses in the pagination bar. (Default: false)
      • recordCount — Specifies the total number of records available through pagination.
    • bb-multiselect-actions(Deprecated.) Use the summary actionbar component component instead. (Optional.) Specifies an array of actions with the following properties to display in the multi-select action bar.
      • actionCallback(Deprecated.) Use the summary actionbar component component instead. Specifies a function to be called when users click the action.
      • automationId(Deprecated.) Use the summary actionbar component component instead. (Optional.) Specifies a unique identifier to place in the data-bbauto attribute for automation purposes.
      • isPrimary(Deprecated.) Use the summary actionbar component component instead. (Optional.) Indicates whether to use the primary button color for the action. To use the primary button color, set this property to true.
      • selections(Deprecated.) Use the summary actionbar component component instead. Specifies the row objects from the grid to associate with the action. You can update this through the bb-selections-updated function.
      • title(Deprecated.) Use the summary actionbar component component instead. Specifies the text to display on the button for the action.
    • bb-selected-rows(Deprecated.) Use bb-grid-multiselect-id-propery and bb-grid-multiselect-selected-ids instead. (Optional.) Specifies an object with two-way binding to multi-selected rows. It can set the multi-selected rows from the bb-grid directive's parent controller.
    • bb-selections-updated(Deprecated.) Listen for the bbGridMultisselectSelectedIdsChanged event instead. (Optional.) Specifies a function to be called when users update multi-select selections. The selections are passed to the function as an argument, and you can update multi-select actions accordingly.
    • bb-grid-multiselect-id-property(Optional.) Specifies the property on a row in the grid data that will be used as a unique identifier for multiselect.
    • bb-grid-multiselect-selected-ids(Optional.) Specifies an array of unique identifiers for rows in the grid data that are selected.
    • bb-grid-infinite-scroll(Optional.) When present, indicates that the grid will use infinite scroll to load instead of the load more button. When using infinite scroll, you must load data with the loadMoreRows event promise property.

Grid events

  • bbGridMultiselectSelectedIdsChanged — Fires when selected rows in the grid are changed. The event contains the following data:
    • selectedIds — An array of unique identifiers for rows that have been selected.
  • includedColumnsChanged — Fires when users change the columns to display in the grid.
    • willResetData — Indicates whether to reload the grid with data from the server after users change the columns to display. To reload the grid, set this property to true on the event handler's data parameter. This avoids reloading the grid with existing data after the includedColumnsChanged event fires.
  • loadMoreRows — Fires when users change pages in paginated grids or load more rows in nonpaginated grids. When users change pages, the event includes a data object with top and skip parameters so that the calling controller can retrieve the proper paged data. When users load more rows.
    • top — Indicates how many records to retrieve and display in the grid. The value is the same as the itemsPerPage property in the bb-grid-pagination directive.
    • skip — Indicates how many records to skip before the first record displayed in the grid. The value equals the number of pages skipped multiplied by the number of items per page.
    • promise — Provides a promise that the consumer of the event can resolve to notify infinite scroll that data has finished loading.
  • columnsResized — Fires after users resize the columns in the grid. You can use this event to listen for column size changes and save them for subsequent visits to the grid. The event contains an object with the following properties:
    • index — Specifies the index of the resized column.
    • newWidth — Specifies the width of the resized column.
  • reInitGrid — The grid reinitializes itself when it receives this event.

Viewkeeper configuration

  • bbViewKeeperConfig — A global configuration object for a service that fixes the grid headers and toolbar in place when the browser window scrolls.
    • hasOmnibar(Optional.) Indicates whether the viewkeeper leaves space for an omnibar. (Default: true)

Demo


Grid with vertical loading

{{sortItem.label}} {{item.label}} Guitar action ({{gridCtrl.action1Selections.length}}) Drum action ({{gridCtrl.action2Selections.length}})

Markup

<div>
    <div ng-controller="PaginationGridTestController as pagedCtrl">
      <bb-tile bb-tile-header="'Grid with pagination in tile'">
          <bb-grid bb-grid-options="pagedCtrl.gridOptions2" bb-grid-pagination="pagedCtrl.paginationOptions">
              <div class="bb-filters-inline">
                  <div class="form-inline">
                      <div class="form-group">
                          <select class="form-control" ng-model="pagedCtrl.gridOptions2.filters.selectFilter">
                                <option value="">All Values</option>
                                <option value="option1">Option 1</option>
                                <option value="option2">Option 2</option>
                            </select>
                            <label>
                                <input 
                                    bb-check
                                    type="checkbox" 
                                    ng-model="pagedCtrl.gridOptions2.filters.checkFilter"/>
                                    Check 1 Really long Labelll
                            </label>
                      </div>
                  </div>
                  
              </div>
              <bb-grid-toolbar
                bb-grid-search="pagedCtrl.onGridSearch(searchText)">
              </bb-grid-toolbar>
          </bb-grid>
      </bb-tile>
      <div class="clearfix"></div>

    </div>
    <hr />

    <h3>Grid with vertical loading</h3>

    <div ng-controller="GridTestController as gridCtrl">
      <button type="button" class="btn btn-primary" ng-click="gridCtrl.setSelections()">Set drum selection</button>
      <button 
        type="button"
        class="btn bb-btn-secondary"
        ng-click="gridCtrl.summaryIsDismissible = !gridCtrl.summaryIsDismissible">
        Toggle summary dismissible
    </button>

      <div style="margin-top: 10px; margin-bottom: 10px;">
          <button class="btn bb-btn-secondary" ng-click="gridCtrl.gridOptions.loading = true;">Begin loading</button>
          <button class="btn bb-btn-secondary" ng-click="gridCtrl.gridOptions.loading = false;">End loading</button>
      </div>

      <bb-grid 
        bb-grid-options="gridCtrl.gridOptions" 
        bb-grid-multiselect-id-property="id"
        bb-grid-multiselect-selected-ids="gridCtrl.selectedIds"
        bb-grid-infinite-scroll>
          <bb-grid-toolbar
            bb-grid-filter-click="gridCtrl.openFilters()"
            bb-grid-search="gridCtrl.onGridSearch(searchText)"
            >

              <button type="button" class="btn bb-btn-secondary bb-grid-toolbar-btn" ng-click="gridCtrl.clickCustom()">This is a custom button</button>
              <bb-grid-toolbar-sort>
                  <bb-sort bb-sort-append-to-body>
                    <bb-sort-item 
                        ng-repeat="sortItem in gridCtrl.sortOptions" 
                        bb-sort-item-select="gridCtrl.sortItems(sortItem)">
                    {{sortItem.label}}
                    </bb-sort-item>
                </bb-sort>
              </bb-grid-toolbar-sort>
              <bb-grid-toolbar-filter-summary>
                  <bb-filter-summary ng-show="gridCtrl.appliedFilters.length > 0">
                    <bb-filter-summary-item
                        ng-repeat="item in gridCtrl.appliedFilters"
                        bb-filter-summary-item-on-click="gridCtrl.openFilters()"
                        bb-filter-summary-item-on-dismiss="gridCtrl.onDismissFilter($index)"
                        bb-filter-summary-item-is-dismissible="gridCtrl.summaryIsDismissible"
                        >
                        {{item.label}}
                    </bb-filter-summary-item>
                </bb-filter-summary>
              </bb-grid-toolbar-filter-summary>
              
          </bb-grid-toolbar>
      </bb-grid>
      <bb-summary-actionbar 
        ng-show="gridCtrl.actionsShown()">
        <bb-summary-actionbar-actions>
            <bb-summary-actionbar-primary
                bb-summary-action-disabled="gridCtrl.action1Selections.length < 1" 
                bb-summary-action-click="gridCtrl.action1Clicked()">
                Guitar action ({{gridCtrl.action1Selections.length}})
            </bb-summary-actionbar-primary>
            <bb-summary-actionbar-secondary-actions>
                <bb-summary-actionbar-secondary
                    bb-summary-action-disabled="gridCtrl.action2Selections.length < 1" 
                    bb-summary-action-click="gridCtrl.action2Clicked()">
                    Drum action ({{gridCtrl.action2Selections.length}})
                </bb-summary-actionbar-secondary>
            </bb-summary-actionbar-secondary-actions>
        </bb-summary-actionbar-actions>
    </bb-summary-actionbar>

      <div class="clearfix"></div>
    </div>

</div>

<script type="text/ng-template" id="demo/grids/filters.html">
    <bb-modal>
        <div class="modal-form">
            <bb-modal-header>Instrument filter</bb-modal-header>
            <div bb-modal-body>
                <form>
                    <div>
                      <label><input bb-check type="checkbox" ng-model="filterCtrl.filters.playsGuitar"/> Show guitar players</label>
                    </div>
                    <div>
                      <label><input  bb-check type="checkbox" ng-model="filterCtrl.filters.playsDrums"/> Show drum players</label>
                    </div>
                </form>
            </div>
            <bb-filter-modal-footer
                bb-filter-modal-apply="filterCtrl.applyFilters()"
                bb-filter-modal-clear="filterCtrl.clearAllFilters()">
            </bb-filter-modal-footer>
        </div>
    </bb-modal>
</script>

JavaScript

/*global angular, alert*/
//A comment

(function () {
    'use strict';

    function RunTemplateCache($templateCache) {
        $templateCache.put('bbGrid/samples/date.html', '<div>{{data | date: \'medium\'}}</div>');

        $templateCache.put('bbGrid/samples/gridtooltip.html',
                          '<div style="height: 70px; width: 300px;"><a>On your face</a></div>');
        $templateCache.put('bbGrid/samples/mycolumn.html',
            '<div>' +
                '<div><span class="bb-grid-no-search"> Title: </span>{{data.title}}</div>' +
                '<a href="" tooltip-trigger="focus" tooltip-placement="bottom" uib-tooltip-template="\'bbGrid/samples/gridtooltip.html\'"> <span class="bb-grid-no-search"> Info:</span> {{data.info}}</a>' +
                '<button class="btn btn-success" ng-click="templateCtrl.clickIt()">My Button</button>' +
            '</div>');
    }

    function TemplateController($scope) {
        var self = this;

        self.clickIt = function () {
            alert('Column button clicked, id: ' + $scope.rowData.id);
        };
    }

    function GridFilterController($uibModalInstance, existingFilters) {
        var self = this;

        function clearAllFilters() {
            self.filters = {
            };
        }
        
        function transformFiltersToArray(filters) {
            var result = [];

            if (filters.playsGuitar) {
                result.push({name: 'guitar', value: true, label: 'plays guitar'});
            }

            if (filters.playsDrums) {
                result.push({name: 'drums', value: true, label: 'plays drums'});
            }

            return result;
        }

        function transformArrayToFilters(array) {
            var i,
                filters = {};

            for (i = 0; i < array.length; i++) {
                if (array[i].name === 'guitar') {
                    filters.playsGuitar = array[i].value;
                }

                if (array[i].name === 'drums') {
                    filters.playsDrums = array[i].value;
                }
            }

            return filters;
        }

        function applyFilters() {
            var result = transformFiltersToArray(self.filters);
            $uibModalInstance.close(result);
        }


        if (!existingFilters) {
            clearAllFilters();
        } else {
            self.filters = transformArrayToFilters(existingFilters);
        }

        self.clearAllFilters = clearAllFilters;
        self.applyFilters = applyFilters;
    }

    function GridTestController($scope, $filter, $timeout, bbModal) {

        var newDataFlag = 0,
            action1,
            action2,
            dataSetBand = [
                {
                    id: 'blaarrrh',
                    name: 'John',
                    instrument: 'Rhythm guitar',
                    bio: '',
                    templated: {
                        title: 'Johnny',
                        info: 'JInfo'
                    },
                    mydate: Date.parse('1/21/2015')
                },
                {
                    id: 'PaulId',
                    name: 'Paul',
                    instrument: 'Bass',
                    bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus in purus odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec consequat ante et felis accumsan volutpat. Nulla leo leo, lacinia nec felis sit amet, tristique feugiat ipsum. Mauris ac velit in mi aliquam auctor vel ac leo. Nullam vehicula congue risus, vitae congue turpis iaculis at. Vestibulum imperdiet tellus erat, sit amet rhoncus neque fringilla vitae.',
                    templated: {
                        title: 'Paully',
                        info: 'PInfo'
                    },
                    mydate: Date.parse('2/23/2012')
                },
                {
                    id: 'GeorgeId',
                    name: 'George',
                    instrument: 'Lead guitar',
                    bio: '',
                    templated: {
                        title: 'Georgy',
                        info: 'GInfo'
                    },
                    mydate: Date.parse('4/14/1999')
                },
                {
                    id: 'RingoId',
                    name: 'Ringo',
                    instrument: 'Drums',
                    bio: '',
                    templated: {
                        title: 'Ringoy',
                        info: 'RInfo'
                    },
                    mydate: Date.parse('6/22/1989')
                }
            ],
            self = this;

        function actionsShown() {
            return (self.action1Selections && self.action1Selections.length > 0) || (self.action2Selections && self.action2Selections.length > 0);
        }

        self.actionsShown = actionsShown;

        function getItemById(id) {
            var i;
            for (i = 0; i < self.gridOptions.data.length; i++) {
                if (id === self.gridOptions.data[i].id) {
                    return self.gridOptions.data[i];
                }
            }
        }

        function updateActions(selectedIds) {
            var i,
                selection;

            self.action1Selections = [];
            self.action2Selections = [];

            for (i = 0; i < selectedIds.length; i++) {
                selection = getItemById(selectedIds[i]);
                if (selection.instrument.indexOf('guitar') > -1) {
                    self.action1Selections.push(selection);
                } else if (selection.instrument.indexOf('Drum') > -1) {
                    self.action2Selections.push(selection);
                }
            }
        }

        function action1Clicked() {
            var i,
                message = 'The selected guitar players are ';
            if (self.action1Selections && self.action1Selections.length > 0) {
                for (i = 0; i < self.action1Selections.length; i = i + 1) {
                    message += self.action1Selections[i].name;
                    if (i !== (self.action1Selections.length - 1)) {
                        message += ', ';
                    }
                }
                alert(message);
            }
        }

        self.action1Clicked = action1Clicked;


        function action2Clicked() {
            var message = 'Drum Drum Drum!';

            alert(message);
        }

        self.action2Clicked = action2Clicked;

        function search(array, text) {
            if (angular.isDefined(text) && text !== '') {
                return array.filter(function (element) {
                    var check = ((element.name.indexOf(text) > -1) ||
                            (element.instrument.indexOf(text) > -1) ||
                            (element.bio.indexOf(text) > -1) ||
                            (element.templated.info.indexOf(text) !== -1) ||
                            (($filter('date')(element.mydate, 'medium')).indexOf(text) > -1));
                    return check;
                });

            } else {
                return array;
            }
        }


        function filter(array, filters) {
            var i,
                item,
                newData = [];
            if (angular.isDefined(filters) &&  filters.length > 0) {
                for (i = 0; i < filters.length; i++) {
                    item = filters[i];
                    if (item.name === 'guitar') {
                        newData.push.apply(newData, [dataSetBand[0], dataSetBand[1], dataSetBand[2]]);
                    }
                    if (item.name === 'drums') {
                        newData.push(dataSetBand[3]);
                    }
                }
                return newData;
            } else {
                return array;
            }
        }

        function filterAndSearch(searchText, filters) {
            var filteredData = [],
                searchedData = [];

            filteredData = filter(dataSetBand, filters);
            searchedData = search(filteredData, searchText);
            self.gridOptions.data = searchedData;
        }

        function onDismissFilter(index) {
            self.appliedFilters.splice(index, 1);
            filterAndSearch(self.searchText, self.appliedFilters);
        }

        function openFilters() {
            bbModal
                .open({
                    controller: 'GridFilterController as filterCtrl',
                    templateUrl: 'demo/grids/filters.html',
                    resolve: {
                        existingFilters: function () {
                            
                            return angular.copy(self.appliedFilters);
                        }
                    }
                })
                .result
                .then(function (result) {
                    self.appliedFilters = angular.copy(result);
                    filterAndSearch(self.searchText, self.appliedFilters);
                });
        }

        function onGridSearch(searchText) {
            self.searchText = searchText;
            filterAndSearch(self.searchText, self.appliedFilters);
        }

        self.onGridSearch = onGridSearch;

        self.openFilters = openFilters;

        self.onDismissFilter = onDismissFilter;

        self.summaryIsDismissible = true;

        self.clickCustom = function () {
            alert('custom button clicked');
        };

        $timeout(function () {
            self.gridOptions = {
                columns: [
                    {
                        caption: 'Name',
                        id: 1,
                        name: 'name',
                        right_align: true,
                        category: 'My category',
                        description: 'Column description',
                        width_all: 300,
                        width_xs: 100
                    },
                    {
                        caption: 'Instrument',
                        jsonmap: 'instrument',
                        id: 2,
                        name: 'instrument',
                        width_all: 300,
                        width_xs: 100
                    },
                    {
                        caption: 'Biography',
                        jsonmap: 'bio',
                        id: 3,
                        name: 'bio',
                        allow_see_more: true,
                        center_align: true,
                        width_all: 400,
                        width_xs: 100
                    },
                    {
                        caption: 'Templated',
                        jsonmap: 'templated',
                        id: 4,
                        name: 'templated',
                        width_all: 300,
                        template_url: 'bbGrid/samples/mycolumn.html',
                        controller: 'TemplateController as templateCtrl'
                    },
                    {
                        caption: 'Date',
                        jsonmap: 'mydate',
                        id: 5,
                        name: 'mydate',
                        width_all: 200,
                        template_url: 'bbGrid/samples/date.html'
                    }
                ],
                data: dataSetBand,
                getContextMenuItems: function (rowid, rowObject) {
                    if (rowid === 'blaarrrh' || rowObject.name === 'Ringo') {
                        return [
                            {
                                id: 'menu',
                                title: 'Option1',
                                cmd: function () {
                                    alert('Context menu option chosen!');
                                    return false;
                                }
                            }
                        ];
                    }
                },
                multiselect: true,
                selectedColumnIds: [1, 2, 3, 5],
                columnPickerHelpKey: 'bb-security-users.html'
            };



            self.setSelections = setSelections;

            self.selectedIds = [dataSetBand[1].id];

            self.sortOptions = [
                {
                    id: 1,
                    label: 'Name (A - Z)',
                    name: 'name',
                    descending: false
                },
                {
                    id: 2,
                    label: 'Name (Z - A)',
                    name: 'name',
                    descending: true
                },
                {
                    id: 3,
                    label: 'Instrument (A - Z)',
                    name: 'instrument',
                    descending: false
                },
                {
                    id: 4,
                    label: 'Instrument (Z - A)',
                    name: 'instrument',
                    descending: true
                },
                {
                    id: 5,
                    label: 'Date (newest first)',
                    name: 'mydate',
                    descending: true

                },
                {
                    id: 6,
                    label: 'Date (oldest first)',
                    name: 'mydate',
                    descending: false
                }
            ];

            

            function sortItems(item) {
                self.gridOptions.data.sort(function (a, b) {
                    var descending = item.descending ? -1 : 1,
                        sortProperty = item.name;
                    if (a[sortProperty] > b[sortProperty]) {
                        return (descending);
                    } else if (a[sortProperty] < b[sortProperty]) {
                        return (-1 * descending);
                    } else {
                        return 0;
                    }
                });

                self.gridOptions.sortOptions = {
                    column: item.name,
                    descending: item.descending
                };
            }

            self.sortItems = sortItems;

            function setSelections() {
                self.selectedIds = [dataSetBand[3].id];
            }

            self.gridOptions.hasMoreRows = true;
            self.action1Selections = [];
            self.action2Selections = [];

            /* This function creates unique data sets to be appended to our
               grid */
            function getLoadMoreDataSet() {
                var i,
                    newData;

                newData = angular.copy(dataSetBand);

                for (i = 0; i < dataSetBand.length; i++) {
                    newData[i].id = newDataFlag;
                    newDataFlag++;
                }
                
                return newData;
            }

            $scope.$on('loadMoreRows', function (event, data) {
                $timeout(function () {
                    self.gridOptions.hasMoreRows = false;
                    self.gridOptions.data = self.gridOptions.data.concat(getLoadMoreDataSet());
                    data.promise.resolve();
                }, 2000);
            });

            $scope.$on('bbGridMultiselectSelectedIdsChanged', function (event, selectedIds) {
                event.preventDefault();
                event.stopPropagation();
                updateActions(selectedIds);
            });

            $scope.$on('includedColumnsChanged', function (event, data) {
                // Optionally set the data's willResetData property to true if the controller will handle reloading the results
                // after the user has changed the selected grid columns.
            });
        });
    }

    function PaginationGridTestController($scope) {
        var dataSet1 = [
            {
                name: 'Patrick',
                skills: 'Karate, Kung Fu, Italian cooking, Ditch digging'
            },
            {
                name: 'Paul',
                skills: 'Arguing',
                cats: '13'
            },
            {
                name: 'George',
                skills: 'Curiousity',
                cats: '1'
            },
            {
                name: 'Ringo',
                skills: 'Slow typing'
            },
            {
                name: 'Samwise',
                skills: 'Loyalty, Gardening'
            }
        ],
        dataSet2 = [
            {
                name: 'Corey',
                skills: 'Vegetables',
                cats: 'Threve'
            },
            {
                name: 'Daniel',
                skills: 'Arguing, spelunking',
                cats: '1'
            },
            {
                name: 'Rick',
                skills: 'Leadership, Zombie slaying'
            },
            {
                name: 'Jeremey',
                skills: 'Knowledge, Speling',
                cats: 'EleventySeven'
            },
            {
                name: 'Frodo',
                skills: 'Walking, Carrying'
            }
        ],
        dataSet3 = [
            {
                name: 'Gollum',
                skills: 'Precious, Filthy hobbitses, *gollum*'
            },
            {
                name: 'Franklin',
                skills: 'Turtles',
                cats: '13'
            },
            {
                name: 'Tater',
                skills: 'Salad',
                cats: '6'
            },
            {
                name: 'Bev',
                skills: 'Growling'
            },
            {
                name: 'Sean',
                skills: 'Method acting, Drama, Villiany',
                cats: '9'
            }
        ],
        self = this;

        self.gridOptions2 = {
            columns: [
                {
                    caption: 'Name',
                    jsonmap: 'name',
                    id: 1,
                    name: 'name',
                    width_xs: 100,
                    width_all: 300,
                    title: false
                },
                {
                    caption: 'Skills',
                    jsonmap: 'skills',
                    id: 2,
                    name: 'skills',
                    allow_see_more: true,
                    width_all: 100
                },
                {
                    caption: 'Number of cats',
                    jsonmap: 'cats',
                    id: 3,
                    name: 'cats'
                }
            ],
            data: dataSet1,
            fixedToolbar: true,
            onAddClick: function () {
                alert('Add button clicked!!');
            },
            onAddClickLabel: 'Add button',
            selectedColumnIds: [1, 2, 3],
            columnPickerHelpKey: 'bb-security-users.html',
            sortOptions: {
                excludedColumns: [
                    'cats',
                    'name',
                    'skills'
                ]
            },
            hasInlineFilters: true,
            filters: {}
        };

        self.paginationOptions = {
            recordCount: 30
        };

        function getPaginationDataSet(top, skip) {
            if (skip === 0 || skip === 15) {
                return dataSet1;
            } else if (skip === 5 || skip === 20) {
                return dataSet2;
            } else {
                return dataSet3;
            }
        }

        function filterItems(filters) {
            self.gridOptions2.filtersAreActive = filters && (filters.checkFilter || filters.selectFilter);

            if (angular.isDefined(filters)) {

                if (filters.checkFilter) {
                    self.gridOptions2.data = [dataSet1[2]];
                    self.paginationOptions.recordCount = 1;
                }

                if (filters.selectFilter) {
                    if (filters.selectFilter === 'option1') {
                        if (filters.checkFilter) {
                            self.gridOptions2.data = [dataSet1[0], dataSet1[2]];
                        } else {
                            self.gridOptions2.data = [dataSet1[0]];
                        }

                        self.paginationOptions.recordCount = self.gridOptions2.data.length;
                        return;
                    } else if (filters.selectFilter === 'option2') {

                        if (filters.checkFilter) {
                            self.gridOptions2.data = [dataSet1[1], dataSet1[2]];
                        } else {
                            self.gridOptions2.data = [dataSet1[1]];
                        }

                        self.paginationOptions.recordCount = self.gridOptions2.data.length;
                        return;
                    }
                } else if (filters.checkFilter) {
                    self.gridOptions2.data = [dataSet1[2]];
                    self.paginationOptions.recordCount = self.gridOptions2.data.length;
                    return;
                }
            }
            self.gridOptions2.data = dataSet1;
            self.paginationOptions.recordCount = 30;
        }

        function search(array, text) {
            var result;
            if (angular.isDefined(text) && text !== '') {
                result = array.filter(function (element) {
                    var check = ((element.name.indexOf(text) > -1) ||
                            (element.skills.indexOf(text) > -1) ||
                            (element.cats && element.cats.indexOf(text) > -1));
                    return check;
                });

                self.paginationOptions.recordCount = result.length;
                return result;
            } else {
                return array;
            }
        }

        function filterAndSearch(searchText, filters) {
            var searchedData = [];

            filterItems(filters);
            searchedData = search(self.gridOptions2.data, searchText);
            self.gridOptions2.data = searchedData;
        }

        $scope.$watch(function () {
            return self.gridOptions2.filters;
        }, function (newValue) {
            filterAndSearch(self.searchText, self.gridOptions2.filters)
        }, true);

        function onGridSearch(searchText) {
            self.searchText = searchText;
            filterAndSearch(self.searchText, self.gridOptions2.filters);
        }
        self.onGridSearch = onGridSearch;

        $scope.$on('loadMoreRows', function (event, data) {
            self.gridOptions2.data = getPaginationDataSet(data.top, data.skip);
        });
    }

    PaginationGridTestController.$inject = ['$scope'];

    RunTemplateCache.$inject = ['$templateCache'];

    TemplateController.$inject = ['$scope'];

    GridFilterController.$inject = ['$uibModalInstance', 'existingFilters']

    GridTestController.$inject = ['$scope', '$filter', '$timeout', 'bbModal'];

    angular.module('stache')
    .run(RunTemplateCache)
    .controller('TemplateController', TemplateController)
    .controller('GridTestController', GridTestController)
    .controller('GridFilterController', GridFilterController)
    .controller('PaginationGridTestController', PaginationGridTestController);

}());