Module: ExtendedTable

ExtendedTable

A table directive with extended functionality as column sorting, column customizing, paging and filtering.

Basic principle is the usage of optional parameters and callbacks, which offer a really flexible API for customizing the table to you very own needs.

Author:
  • Marco Lehmann <marco.lehmann (at) kiwigrid.com>
Source:

Examples

<div data-keta-extended-table
    data-rows="rows"
    data-current-locale="currentLocale"
    data-label-add-column="labelAddColumn"
    data-disabled-components="disabledComponents"
    data-switchable-columns="switchableColumns"
    data-group-by-property="groupByProperty"
    data-order-by-property="orderByProperty"
    data-visible-columns="visibleColumns"
    data-header-label-callback="headerLabelCallback"
    data-operations-mode="operationsMode"
    data-row-sort-enabled="rowSortEnabled"
    data-row-sort-criteria="rowSortCriteria"
    data-row-sort-order-ascending="rowSortOrderAscending"
    data-unsortable-columns="unsortableColumns"
    data-action-list="actionList"
    data-cell-renderer="cellRenderer"
    data-column-class-callback="columnClassCallback"
    data-table-class-callback="tableClassCallback"
    data-row-class-callback="rowClassCallback"
    data-search-input-width-classes="searchInputWidthClasses"
    data-selector-width-classes="selectorWidthClasses"
    data-pager="pager"
    data-search="search"
    data-search-wait-ms="waitTime"
    data-search-results="searchResults"></div>
angular.module('exampleApp', ['keta.directives.ExtendedTable', 'keta.services.Device'])
    .controller('ExampleController', function(
        $scope,
        ketaExtendedTableConstants, ketaExtendedTableMessageKeys, ketaDeviceConstants) {

        // data as array of objects, keys from first element are taken as headers
        $scope.rows = [{
            guid: 'guid-1',
            idName: 'Device 1',
            stateDevice: 'OK',
            deviceClass: 'class-1'
        }, {
            guid: 'guid-2',
            idName: 'Device 2',
            stateDevice: 'ERROR',
            deviceClass: 'class-2'
        }, {
            guid: 'guid-3',
            idName: 'Device 3',
            stateDevice: 'FATAL',
            deviceClass: 'class-3'
        }];

        // override default-labels if necessary
        // get default labels
        $scope.labels = ketaExtendedTableMessageKeys;

        // use case 1: overwrite specific key
        $scope.labels.de_DE['__keta.directives.ExtendedTable_search'] = 'Finde';

        // use case 2: add locale
        $scope.labels.fr_FR = {
            '__keta.directives.ExtendedTable_search': 'Recherche',
            '__keta.directives.ExtendedTable_add_column': 'Ajouter colonne',
            '__keta.directives.ExtendedTable_remove_column': 'Retirer la colonne',
            '__keta.directives.ExtendedTable_sort': 'Sorte',
            '__keta.directives.ExtendedTable_no_entries': 'Pas d’entrées'
        };

        // array of disabled components (default: everything except the table itself is disabled)
        $scope.disabledComponents = [
            // the table itself
            ketaExtendedTableConstants.COMPONENT.TABLE,
            // an input field to search throughout the full dataset
            ketaExtendedTableConstants.COMPONENT.FILTER,
            // a selector to add columns to table
            ketaExtendedTableConstants.COMPONENT.SELECTOR,
            // a pager to navigate through paged data
            ketaExtendedTableConstants.COMPONENT.PAGER
        ];

        // array of switchable columns (empty by default)
        // together with selector component the given columns can be removed from
        // table and added to table afterwards
        // to support grouping in select field an array of objects is required (match is compared by id property)
        $scope.switchableColumns = [{
            id: 'deviceClass'
        }];

        // property to group selector by
        $scope.groupByProperty = 'column.deviceName';

        // property to order selector by
        $scope.orderByProperty = 'tagName';

        // array of visible columns (full by default)
        // use this property to filter out columns like primary keys
        $scope.visibleColumns = ['idName', 'stateDevice', 'deviceClass'];

        // callback method to specify header labels (instead of using auto-generated ones)
        $scope.headerLabelCallback = function(column) {
            var mappings = {
                idName: 'Name',
                stateDevice: 'State',
                deviceClass: 'Device Class'
            };
            return (angular.isDefined(mappings[column])) ? mappings[column] : column;
        };

        // operations mode ("view" for frontend or "data" for backend)
        // by defining operations mode as "view" the directive itself manages sorting,
        // paging and filtering; if you just pass a pre-sorted, pre-paged and pre-filtered
        // dataset by querying a backend, you have to use "data"
        $scope.operationsMode = ketaExtendedTableConstants.OPERATIONS_MODE.VIEW;

        // boolean flag to enable or disable row sorting in frontend by showing appropriate icons
        $scope.rowSortEnabled = true;

        // criteria to sort for as string
        $scope.rowSortCriteria = 'idName';

        // boolean flag to determine if sort order is ascending (true by default)
        $scope.rowSortOrderAscending = true;

        // array of columns (empty by default) that should not be sorted
        $scope.unsortableColumns = ['idName'];

        // Array of actions to render for each row.
        // getLink method will be used to construct a link with the help of the row object,
        // getLabel is used as callback to retrieve value for title-tag,
        // getTitle is used as callback to retrieve value for text right after the icon,
        // target is used as target attribute for the link (e.g. _blank, _self, ...),
        // icon is used as icon-class for visualizing the action.
        // runAction is a callback-function that will be executed when the user clicks on
        // the corresponding button. To use this functionality it is necessary to provide the type-parameter
        // with the value 'action'.
        // type can have the values 'link' (a normal link with href-attribute will be rendered) or
        // 'action' (a link with ng-click attribute to execute a callback will be rendered).
        // For simplicity the type-property can be left out. In this case the directive renders
        // a normal link-tag (same as type 'link').
        // display is an optional callback to return condition for displaying action item based on given row
        $scope.actionList = [{
            getLink: function(row) {
                return 'edit/' + row.guid;
            },
            getLabel: function() {
                return 'Edit';
            },
            getTitle: function() {
                return 'Edit';
            },
            target: '_self',
            icon: 'glyphicon glyphicon-pencil',
            type: ketaExtendedTableConstants.ACTION_LIST_TYPE.LINK
        }, {
            runAction: function(row) {
                console.log('action called with ', row);
            },
            getLabel: function() {
                return 'Remove';
            },
            icon: 'glyphicon glyphicon-remove'
            type: ketaExtendedTableConstants.ACTION_LIST_TYPE.ACTION,
            display: function(row) {
                return row.type !== 'EnergyManager';
            }
        }];

        // callback method to render each cell individually
        // with the help of this method you can overwrite default cell rendering behavior,
        // e.g. suppressing output for stateDevice property
        $scope.cellRenderer = function(row, column) {
            var value = angular.isDefined(row[column]) ? row[column] : null;
            if (column === 'stateDevice') {
                value = '';
            }
            return value;
        };

        // callback method to return class attribute for each column
        // in this example together with cellRenderer the deviceState column is
        // expressed as just a table data element with css classes
        $scope.columnClassCallback = function(row, column, isHeader) {
            var columnClass = '';
            if (column === 'stateDevice') {
                columnClass = 'state';
                if (row.state === ketaDeviceConstants.STATE.OK && !isHeader) {
                    columnClass+= ' state-success';
                }
                if (row.state === ketaDeviceConstants.STATE.ERROR && !isHeader) {
                    columnClass+= ' state-warning';
                }
                if (row.state === ketaDeviceConstants.STATE.FATAL && !isHeader) {
                    columnClass+= ' state-danger';
                }
            }
            return columnClass;
        };

        // callback method to return class attribute for each row
        $scope.rowClassCallback = function(row, isHeader) {
            var rowClass = 'row-is-selected';
            if (isHeader) {
                rowClass += ' header-row';
            } else if (angular.isDefined(row.connected) && row.connected === true) {
                rowClass += ' connected';
            }
            return rowClass;
        };

        // callback method to return class array for table
        $scope.tableClassCallback = function() {
            return ['table-striped'];
        };

        // bootstrap width classes to define the size of the search input
        $scope.searchInputWidthClasses = 'col-xs-12 col-sm-6';

        // bootstrap width classes to define the size of the selector dropdown
        $scope.selectorWidthClasses = 'col-xs-12 col-sm-6 col-md-6 col-lg-6';

        // object for pager configuration (total, limit, offset)
        // with this configuration object you are able to manage paging
        // total is the total number of rows in the dataset
        // limit is the number of rows shown per page
        // offset is the index in the dataset to start from
        var pager = {};
        pager[ketaExtendedTableConstants.PAGER.TOTAL] = $scope.allRows.length;
        pager[ketaExtendedTableConstants.PAGER.LIMIT] = 5;
        pager[ketaExtendedTableConstants.PAGER.OFFSET] = 0;
        $scope.pager = pager;

        // search term to filter the table
        // as two-way-binded property this variable contains the search string
        // typed by the user in the frontend and can therefor be used for querying
        // the backend, if watched here additionally
        $scope.search = null;

        // Minimal wait time in milliseconds after last character typed before search kicks-in.
        // updates on blur are instant
        // default is 0
        $scope.waitTime = 500;

        // array of search results e.g. for usage in headlines
        // defaults to $scope.rows, typically not set directly by controller
        //$scope.searchResults = $scope.rows;

    });