初始化多个指令

时间:2014-01-05 05:36:47

标签: angularjs angularjs-directive ng-grid

我是AngularJS的新手。

使用过滤器形式实现数据网格我在主视图中创建了两个指令。

myFilterForm - 是网格中数据的过滤器表单,其中包含以下函数:

  • filter() - 使用表单的模型
  • 触发'filterChanged'事件
  • reset() - 将表单的模型设置为默认值和调用 滤波器()。

为了将过滤器更改传递给网格(以及为简化而删除的其他指令),这些方法使用过滤器对象广播“filterChanged”事件:

    myApp.directive('myFilterForm', [function () {
    return {
    restrict: 'A',
    templateUrl:  'partials/filter-form.html',
    scope: true, // use own scope
    link: function (scope, elem, attrs) {

        // Define a filter object for URL parameters
        scope.formObject = {};

        // Clear the filter:
        scope.resetFilter = function(){
            scope.formObject = angular.copy(scope.defaultFilter);
            scope.$parent.filterOn = false;
            scope.$parent.$broadcast('filterChanged', scope.formObject);
            scope.filterReset = true;
        }


        // Filter the data:
        scope.filter = function(){
            if(scope.filterForm.$dirty){
                scope.$parent.filterOn = true;
            }
            scope.filterForm.$setPristine(); // disable the filter button until some value changes (prevent multiple clicks)
            scope.$parent.$broadcast('filterChanged', scope.formObject);
            scope.filterReset = angular.equals(scope.formObject, scope.defaultFilter);
            console.log("filterReset="+scope.filterReset);
        }

    },
    controller: function($scope, $timeout){

        //TODO: HACK!!!
        var timer = $timeout(
            function() {

                console.log( "Timeout executed", Date.now() );
                $scope.formObject = angular.copy($scope.defaultFilter, $scope.formObject);
                $scope.filterReset = true;
                console.log(">>>>>>>LOADING>>>>>>"+angular.toJson($scope.formObject));
                $scope.$parent.$broadcast('filterChanged', $scope.formObject);

            },
            100
        );
    }
    }}]);

(简化)filter-form.html模板:

    <div class="well">
    <form novalidate name="filterForm" novalidate class="form-horizontal" style="margin-bottom: 0px">
    <input type="text" ng-model="formObject.firstName" class="form-control input-sm">
    </form>
    <button ng-click="resetFilter()" class="btn btn-danger"><i class="fa fa-times fa-fw"></i> Reset</button>
    <button ng-click="filter()" class="btn btn-success"><i class="fa fa-check fa-fw"></i> Filter</button>
    </div>

myDataGrid - 是一个使用服务器端排序和分页

的ng-grid包装器

在myDataGrid中我通过调用$ http来重新加载网格(已过滤)数据来处理'filterChanged'事件。

myApp.directive('myDataGrid', ['serverProxy', '$log', function (serverProxy, $log  ) {
return {
    restrict: 'A',
    replace: false,
    template: '<div cg-busy="\'gridTracker\'" class="gridStyle" ng-grid="gridOptions"></div>',
    scope: true, //ng-grid wrapper should use it own (child) scope (see:  https://github.com/angular-ui/ng-grid/issues/206)
    controller: 'gridCtrl',

    link: function (scope, elem, attrs) {
        if(attrs.apiUrl){
            scope.apiUrl = attrs.apiUrl;
        }

        // holds the item count in the DB with the current filter applied
        scope.totalServerItems = 0;
        // holds the filter form model
        scope.formObject =  {};
        // holds the sorting and paging settings
        scope.paramObject = { limit: scope.pagingOptions.pageSize, page: scope.pagingOptions.currentPage };


        // Watch for changes in ng-grid's currentPage
        scope.$watch('pagingOptions.currentPage', function (newVal, oldVal) {
            if (newVal !== oldVal) {
                scope.paramObject.page = newVal;
                scope.loadData();
            }
        }, true);

        // Watch for changes in ng-grid's pageSize
        scope.$watch('pagingOptions.pageSize', function (newVal, oldVal) {
            if (newVal !== oldVal) {
                scope.pagingOptions.currentPage = 1;// if pageSize changes - start from first page
                scope.paramObject.limit = newVal;
                scope.loadData();
            }
        }, true);

        scope.$watch('sortOptions', function (newVal, oldVal) {
            if (newVal !== oldVal) {
                $log.debug("sortOptions="+angular.toJson(scope.sortOptions.fields));
                scope.paramObject.sort = newVal.fields[0];
                scope.paramObject.direction = newVal.directions[0];
                scope.loadData();
            }
        }, true);


        scope.$on('filterChanged', function(event, filterObj) {
            $log.debug('myDataGrid: caught filterChanged event! - new val='+angular.toJson(filterObj));
            scope.pagingOptions.currentPage = 1;// if filter changes - start from first page
            scope.loadData(filterObj);
        });

        // Update the paging data for the grid:
        scope.setPagingData = function(data, page, pageSize){
            scope.myData = data.content;
            scope.totalServerItems = data.totalElements;
            if (!scope.$$phase) {
                scope.$apply();
            }
        };


        scope.loadData = function (formObject) {
            if(formObject) { scope.formObject = formObject; }
            serverProxy.getData(scope.apiUrl, scope.paramObject, scope.formObject, 'gridTracker', function(data){
                scope.setPagingData(data, scope.pagingOptions.currentPage, scope.pagingOptions.pageSizes);
            });
        };

    }
}}]);

网格的控制器有一些ng-grid默认配置:

myApp.controller('gridCtrl', ['$scope', function($scope) {

$scope.pagingOptions = {
    pageSizes: [10, 25, 50, 198],
    pageSize: 10,
    currentPage: 1
};

$scope.sortOptions = {
    columns: [],
    fields: [],
    directions: []
};

$scope.gridOptions = {
    data: 'myData',
    columnDefs: $scope.gridColumnDefs, // should be defined in the view's controller
    enablePaging: true,
    showFooter: true,
    totalServerItems: 'totalServerItems',
    pagingOptions: $scope.pagingOptions,
    sortInfo: $scope.sortOptions,//,
    useExternalSorting: true,
    i18n: "en"
};

}]);

最后,主视图有两个指令:

    <div my-filter-form></div>
    <div my-data-grid></div>

并使用控制器设置页面的特定配置:

  • 用于加载数据的服务器URL
  • 网格列
  • 默认过滤器

    myApp.controller('ViewCtrl', ['$scope', function($scope) {
    
    // server URL to get the grid data:
    $scope.apiUrl = '/api/users';
    
    $scope.gridColumnDefs = [
    {field: 'firstName', displayName:'First Name', resizable: true, sortable: true},
    {field: 'lastName', displayName:'Last Name', resizable: true, sortable: true},
    {field: 'roles', displayName:'Roles', resizable: true, sortable: false, cellFilter: 'listProperty:\'name\''},
    {field: 'active', displayName:'Active', resizable: true, sortable: false, cellFilter: 'yesNoBoolean'},
    {field: 'updateDate', displayName:'Update Date', resizable: true, sortable: true, cellFilter: 'date:\'dd MMM yyyy - hh:mm:ss a\''}
    ];
    
    // default filter values 
    $scope.defaultFilter = {
        "firstName": "jimmy"
    };
    
    }]);
    

我希望页面的初始加载能够加载网格和应用了默认过滤器值的表单。

我目前的解决方案是在myFilterForm指令的控制器中设置一个短的$ timeout,它设置默认过滤器并触发'filterChanged'事件。这有效,但感觉就像一个黑客。

有人可能会建议实现这一目标的正确方法。

感谢。

1 个答案:

答案 0 :(得分:1)

找到了一个更好的解决方案,但不涉及$ timeout。 (谢谢m59)

在'myFilterForm'中我删除了控制器功能并在链接功能中添加了以下手表:

scope.$watch('defaultFilter', function (newVal, oldVal) {
    scope.resetFilter();                
}, true);

defaultFilter实际上没有改变 - 它用于将过滤器重置为默认值。但angular会在初始加载时调用watch,这是我需要重置表单并加载数据