Skip to content

Instantly share code, notes, and snippets.

@suvroc
Created March 29, 2016 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suvroc/981f45ccf152db3287fa to your computer and use it in GitHub Desktop.
Save suvroc/981f45ccf152db3287fa to your computer and use it in GitHub Desktop.
Functionality to store grid filtering in query string
(function () {
'use strict';
angular.module('app.kendoState')
.service('kendoStateStore', function ($location, _) {
this.addFilterStoring = addFilterStoring;
this.rememberLocationParametersIn = rememberLocationParametersIn;
function rememberLocationParametersIn(callback) {
var locationParams = getLocationParameters();
callback();
setLocationParameters(locationParams);
}
function addFilterStoring(configuration, customFiltersBuilder) {
// filtering
var locationParams = filtersFromQueryString();
configuration.dataSource.filter = megreConfigurations(configuration.dataSource.filter, locationParams ? locationParams.filters : []);
// sorting
var sortParams = sortFromQueryString();
configuration.dataSource.sort = megreConfigurations(configuration.dataSource.sort, sortParams || []);
// dataSource.transport.read
var oldReadFunction = configuration.dataSource.transport.read;
configuration.dataSource.transport.read = function (optionsData) {
var data = oldReadFunction.call(this, optionsData);
setTimeout(function () { applyFilterInQueryString(data, customFiltersBuilder()); }, 500);
}
return configuration;
}
function megreConfigurations(parameters, queryParameter) {
var resultFilter = [];
for (var i = 0; i < parameters.length; i++) {
var userFilter = parameters[i];
var matchedItems = queryParameter.filter(function (singleFilter) { return singleFilter.field === userFilter.field });
if (matchedItems.length === 0) {
resultFilter.push(userFilter);
}
}
resultFilter = resultFilter.concat(queryParameter);
return resultFilter;
}
function setLocationParameters(params) {
$location.search(params);
}
function getLocationParameters() {
return $location.search();
}
function filtersFromQueryString() {
if (!angular.equals($location.search(), {})) {
return parseFilterString($location.search().filter);
}
return null;
}
function sortFromQueryString() {
if (!angular.equals($location.search(), {})) {
return parseSortString($location.search().sort);
}
return null;
}
function applyFilterInQueryString(stringObject, additionalProps) {
var data = {
filter: stringObject.filter,
sort: stringObject.sort
};
angular.extend(data, additionalProps);
$location.search(data);
}
function parseFilterString(filterString) {
// Remove all of the ' characters from the string.
filterString = filterString.replace(/[']/g, '');
// Split the string into an array of strings, using the ~ as a delimiter.
var ss = filterString.split("~"); // ss stands for "split string". I'm clever.
var F = []; // Used to store all of the parsed filters.
var fIndex = -1; // Used to track filter index.
var cIndex = 0; // Used to track filter index within a composite filter object.
var isComposite = false; // Used to indicate if a composite filter is currently being parsed.
for (var i = 0; i < ss.length; i++) {
if (i % 4 == 0) { // Field.
if (ss[i].indexOf('(') > -1) { // If we're starting a composite object, create a composite object and add it to the parsed filters.
F.push({
filters: [],
logic: ""
});
fIndex++; // We added an object to the array, so increment the counter.
//F[fIndex]
F[fIndex].filters.push({
field: ss[i].replace('(', ''),
operator: "",
value: ""
});
cIndex = 0; // We added the first filter to the composite object, so set the counter.
isComposite = true;
}
else if (isComposite) { // If we're parsing the second filter in a composite filter object, then add the field to the child filter.
F[fIndex].filters.push({
field: ss[i],
operator: "",
value: ""
});
cIndex++; // We added the second filter to the composite object, so increment the counter.
}
else { // Add the field as normal.
F.push({
field: ss[i],
operator: "",
value: ""
});
fIndex++; // We added an object to the array, so increment the counter.
}
}
if (i % 4 == 1) { // Operator.
if (isComposite) {
F[fIndex].filters[cIndex].operator = ss[i];
}
else {
F[fIndex].operator = ss[i];
}
}
if (i % 4 == 2) { // Value.
if (ss[i].indexOf(')') > -1) {
F[fIndex].filters[cIndex].value = ss[i].replace(')', '');
isComposite = false;
}
else if (isComposite) {
F[fIndex].filters[cIndex].value = ss[i];
}
else {
F[fIndex].value = ss[i];
}
}
if (i % 4 == 3) { // Logic.
if (isComposite) {
F[fIndex].logic = ss[i]; // Add the logic to the composite filter object.
}
// If the filter is not composite, the logic will always be "and". So, we just don't do anything if that's the case.
}
}
return {
filters: F,
logic: "and"
};
};
function parseSortString(sortString) {
// Split the string into an array of strings, using the ~ as a delimiter.
var ss = sortString.split("~"); // ss stands for "split string". I'm clever.
var S = []; // Array containing sort objects.
for (var i = 0; i < ss.length; i++) {
var sort = ss[i].split('-'); // Split sort string into field and direction.
S.push({
compare: undefined, // This field exists in the sort objects, but is always undefined (as far as I can tell). I added it anyways, to minimize potential future issues.
dir: sort[1], // Direction.
field: sort[0] // Field.
});
}
return S;
};
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment