我是AngularJS的新手。
使用过滤器形式实现数据网格我在主视图中创建了两个指令。
myFilterForm - 是网格中数据的过滤器表单,其中包含以下函数:
为了将过滤器更改传递给网格(以及为简化而删除的其他指令),这些方法使用过滤器对象广播“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>
并使用控制器设置页面的特定配置:
默认过滤器
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'事件。这有效,但感觉就像一个黑客。
有人可能会建议实现这一目标的正确方法。
感谢。
答案 0 :(得分:1)
找到了一个更好的解决方案,但不涉及$ timeout。 (谢谢m59)
在'myFilterForm'中我删除了控制器功能并在链接功能中添加了以下手表:
scope.$watch('defaultFilter', function (newVal, oldVal) {
scope.resetFilter();
}, true);
defaultFilter实际上没有改变 - 它用于将过滤器重置为默认值。但angular会在初始加载时调用watch,这是我需要重置表单并加载数据