Well, it's not a pretty solution but it does seam to do what I need by combining Angular with jQuery! I decided to go with an attribute/directive (st-search-cookie) on the tr tag that contains the search fields. For example:
<tr st-search-cookie>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
You can optionally define the cookie-name and collection-name on the directive. Otherwise, it uses the md5 hash of all the available search fields as the collection-name. The idea being that you have a single cookie that can have collections for many different tables instead of having lots of cookies (i.e. having to have one for every table).
Anyway, this automatically finds the default st-search input boxes (input[st-search]) as well as any with the *predicate' attribute (input[predicate]) that are commonly used when making custom search directives.
Hopefully someone else will find this useful or, even better, improve on it!
(function(angular) {
angular.module("stSearchCookie", ['ngCookies', 'angular-md5']).directive('stSearchCookie', function ($cookies, md5, $log) {
return {
restrict: 'A',
scope: {
'cookieName': '@',
'collectionName': '@'
},
transclude: false,
link: {
post: function (scope, elem, attrs, controller) {
// Set Defaults for scope
if (angular.isUndefined(scope.cookieName)) {
scope.cookieName = 'stSearchParams';
$log.log('cookie-name not defined so defaulting to "' + scope.cookieName + '"');
}
if (angular.isUndefined(scope.collectionName)) {
var fields = 'fieldNames=';
$.each(elem.find('input[st-search]'), function(i, e) {
fields = fields + $(e).attr('st-search') + ';';
});
$.each(elem.find('input[predicate]'), function (i, e) {
fields = fields + $(e).attr('predicate') + ';';
});
scope.collectionName = md5.createHash(fields);
$log.log('collection-name not defined so defaulting to "' + scope.collectionName + '"');
}
// Set defaults in cookie
var defaults = {};
$.each(elem.find('input[st-search]'), function(i, e) {
defaults[$(e).attr('st-search')] = '';
});
$.each(elem.find('input[predicate]'), function (i, e) {
defaults[$(e).attr('predicate')] = '';
});
var cookieData = $cookies.getObject(scope.cookieName);
if (angular.isObject(cookieData)) {
if (cookieData.hasOwnProperty(scope.collectionName))
cookieData[scope.collectionName] = angular.extend(defaults, cookieData[scope.collectionName]);
else
cookieData[scope.collectionName] = defaults;
} else {
cookieData = {};
cookieData[scope.collectionName] = defaults;
}
$cookies.putObject(scope.cookieName, cookieData);
// Populate from cookie
$.each(Object.keys(cookieData[scope.collectionName]), function (index, key) {
$('input[st-search="' + key + '"]').val(cookieData[scope.collectionName][key]).trigger('change').trigger('blur');
});
$.each(Object.keys(cookieData[scope.collectionName]), function (index, key) {
$('input[predicate="' + key + '"]').val(cookieData[scope.collectionName][key]).trigger('change').trigger('blur');
});
// Add events to update cookie on changes
elem.find('input[st-search]').on('change blur', function(event) {
var target = $(event.target);
var cookieData = $cookies.getObject(scope.cookieName);
cookieData[scope.collectionName][target.attr('st-search')] = target.val();
$cookies.putObject(scope.cookieName, cookieData);
});
elem.find('input[predicate]').on('change blur', function (event) {
var target = $(event.target);
var cookieData = $cookies.getObject(scope.cookieName);
cookieData[scope.collectionName][target.attr('predicate')] = target.val();
$cookies.putObject(scope.cookieName, cookieData);
});
}
}
};
});
})(angular);