Skip to content

Commit

Permalink
Merge pull request #639 from marmelab/filter_default_value
Browse files Browse the repository at this point in the history
[RFR] Introducing filter default value
  • Loading branch information
fzaninotto committed Sep 1, 2015
2 parents 0ad9b5f + bc7084d commit 6b308ae
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 100 deletions.
17 changes: 16 additions & 1 deletion doc/Configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,22 @@ Add filters to the list. Each field maps a property in the API endpoint result.
.template('<div class="input-group"><input type="text" ng-model="value" placeholder="Search" class="form-control"></input><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span></div>'),
]);

Note that you can use `map()` and `transform()` on filter fields (see [General Field Settings](#general-field-settings)).
Note that you can use `map()` and `transform()` on filter fields (see [General Field Settings](#general-field-settings)). You can also use `defaultValue()` on filter fields, so as to filter the list as soon as the filter is added. Combined with an empty template, this allows to create "tagged" lists:

var user_id = 123; // currently logged user
var d = new Date()
var yesterday = d.setDate(d.getDate() - 1);
listView.filters([
nga.field('flagged', 'template')
.defaultValue('true'), // adds ?flagged=true to the REST query
nga.field('author_id', 'template')
.label('Mine')
.defaultValue(user_id), // adds ?author_id=123 to the REST query
nga.field('created_at', 'template')
.label('Recent')
.defaultValue({ gt: yesterday }), // adds ?created_at={gt:2015-08-31} to the REST query
]);


* `permanentFilters({ field1: value, field2: value, ...})`
Add permanent filters to the results list.
Expand Down
4 changes: 3 additions & 1 deletion examples/blog/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@
.template('{{ entry.values.name.toUpperCase() }}')
])
.filters([
nga.field('published', 'boolean')
nga.field('published', 'template')
.label('Not yet published')
.defaultValue(false)
])
.batchActions([]) // disable checkbox column and batch delete
.listActions(['show', 'edit']);
Expand Down
16 changes: 10 additions & 6 deletions src/javascripts/ng-admin/Crud/filter/maFilter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
var FilterController = require('./maFilterController');
var _ = require('lodash');

function maFilterDirective(FieldViewConfiguration) {
Expand All @@ -11,10 +10,10 @@ function maFilterDirective(FieldViewConfiguration) {

var template = `
<div class="row">
<form class="filters col-md-offset-6 col-md-6 form-horizontal" ng-if="filterCtrl.shouldFilter()">
<form class="filters col-md-offset-6 col-md-6 form-horizontal" ng-if="shouldFilter()">
<div class="filter form-group input-{{ field.type() }}" ng-repeat="field in filters track by $index">
<div class="col-sm-1 col-xs-1 remove_filter">
<a ng-if="!field.pinned()" ng-click="filterCtrl.removeFilter(field)"><span class="glyphicon glyphicon-remove"></span></a>
<a ng-if="!field.pinned()" ng-click="removeFilter(field)"><span class="glyphicon glyphicon-remove"></span></a>
</div>
<label for="{{ field.name() }}" class="col-sm-4 col-xs-11 control-label">
{{ field.label() }}<span ng-if="field.validation().required">&nbsp;*</span>&nbsp;
Expand All @@ -33,10 +32,15 @@ function maFilterDirective(FieldViewConfiguration) {
scope: {
filters: '=',
datastore: '&',
values: '&'
values: '&',
removeFilter: '&'
},
controllerAs: 'filterCtrl',
controller: FilterController
link: function(scope) {
scope.values = scope.values();
scope.datastore = scope.datastore();
scope.removeFilter = scope.removeFilter();
scope.shouldFilter = () => Object.keys(scope.filters).length;
}
};
}

Expand Down
80 changes: 0 additions & 80 deletions src/javascripts/ng-admin/Crud/filter/maFilterController.js

This file was deleted.

67 changes: 56 additions & 11 deletions src/javascripts/ng-admin/Crud/list/ListLayoutController.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
var ListLayoutController = function ($scope, $stateParams, $location, $timeout, view, dataStore) {
var ListLayoutController = function ($scope, $stateParams, $state, $location, $timeout, view, dataStore) {
this.$scope = $scope;
this.$state = $state;
this.$stateParams = $stateParams;
this.$location = $location;
this.$timeout = $timeout;
this.view = view;
this.dataStore = dataStore;
this.entity = view.getEntity();
this.actions = view.actions();
this.batchActions = view.batchActions();
this.loadingPage = false;
this.search = $location.search().search ? JSON.parse($location.search().search) : {};
$scope.$watch(() => this.search, _.debounce((newValues, oldValues) => {
if (newValues != oldValues) {
this.updateFilters();
}
}, 500), true);
this.filters = view.filters();
this.enabledFilters = this.filters.filter(filter => {
if (filter.pinned()) return true;
return this.search && (filter.name() in this.search)
});
this.hasFilters = Object.keys(this.filters).length > 0;
this.focusedFilterId = null;
// required to pass enableFilter down 2 directives to the filterButton
var self = this;
this.enableFilter = function(filter) {
self.enabledFilters.push(filter);
self.focusedFilterId = filter.name();
$timeout(() => window.document.getElementById(self.focusedFilterId).focus(), 200);
}
this.enableFilter = this.enableFilter.bind(this);
this.removeFilter = this.removeFilter.bind(this);
if (this.batchActions.length) {
// required in scope to communicate with listView
$scope.selectionUpdater = selection => $scope.selection = selection;
Expand All @@ -32,13 +33,57 @@ var ListLayoutController = function ($scope, $stateParams, $location, $timeout,
$scope.$on('$destroy', this.destroy.bind(this));
};

ListLayoutController.prototype.enableFilter = function (filter) {
let defaultValue = filter.defaultValue();
if (defaultValue !== null) {
this.search[filter.name()] = defaultValue;
}
this.enabledFilters.push(filter)
this.focusedFilterId = filter.name();
this.$timeout(() => {
let el = window.document.getElementById(this.focusedFilterId);
el && el.focus && el.focus();
}, 200, false);
}

ListLayoutController.prototype.updateFilters = function () {
var values = {},
filters = this.enabledFilters,
fieldName,
field,
i;
for (i in filters) {
field = filters[i];
fieldName = field.name();
if (this.search[fieldName] === '') {
delete this.search[fieldName];
continue;
}

if ((field.type() === 'boolean' && this.search[fieldName]) || // for boolean false is the same as null
(field.type() !== 'boolean' && this.search[fieldName] !== null)) {
values[fieldName] = this.search[fieldName];
}
}

this.$stateParams.search = values;
this.$stateParams.page = 1;
this.$state.go('list', this.$stateParams);
};

ListLayoutController.prototype.removeFilter = function(filter) {
delete this.search[filter.name()];
this.enabledFilters = this.enabledFilters.filter(f => f !== filter);
};

ListLayoutController.prototype.destroy = function () {
this.$scope = undefined;
this.$state = undefined;
this.$stateParams = undefined;
this.$location = undefined;
this.$timeout = undefined;
this.dataStore = undefined;
};

ListLayoutController.$inject = ['$scope', '$stateParams', '$location', '$timeout', 'view', 'dataStore'];
ListLayoutController.$inject = ['$scope', '$stateParams', '$state', '$location', '$timeout', 'view', 'dataStore'];

module.exports = ListLayoutController;
2 changes: 1 addition & 1 deletion src/javascripts/ng-admin/Crud/list/listLayout.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1 compile="::llCtrl.view.title()">
<p class="lead" ng-if="::llCtrl.view.description()" compile="::llCtrl.view.description()">{{ ::llCtrl.view.description() }}</p>
</div>

<ma-filter ng-if="llCtrl.hasFilters" filters="llCtrl.enabledFilters" values="::llCtrl.search" datastore="::llCtrl.dataStore"></ma-filter>
<ma-filter ng-if="llCtrl.hasFilters" filters="llCtrl.enabledFilters" values="::llCtrl.search" datastore="::llCtrl.dataStore" remove-filter="::llCtrl.removeFilter"></ma-filter>

</div>
</div>
Expand Down

0 comments on commit 6b308ae

Please sign in to comment.