Правильный способ просмотра / обновления группы входов в AngularJS
В настоящее время я работаю над изучением AngularJS после нескольких лет работы с JQuery. Прямо сейчас я смотрю на реализацию смарт-таблиц ( http://lorenzofox3.github.io/smart-table-website/) и хотел бы иметь возможность автоматически сохранять поисковые запросы в cookie, чтобы я мог их перезагрузить когда пользователь вернется. В идеале я хотел бы иметь общий способ сделать это, чтобы я мог повторно использовать код, используя одну директиву или DI.
В мире JQuery я бы сделал это:
HTML: одиночная поисковая запись, определенная st-search, но мы можем иметь n-ное число из них с уникальными идентификаторами.
<tr>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
Javascript "onChange": слушайте все обновления полей, чтобы вместо предупреждений я мог вызвать свою службу хранения (возможно, cookie), чтобы сохранить обновленный параметр поиска для этой таблицы.
$('input[st-search]').on('change', function(event){
var target = $(event.target);
alert(target.attr('st-search')+'='+target.val());
});
Инициализация Javascript: это будет принимать cookieData и применять его ко всем соответствующим полям поиска.
$.each(cookieData, function(index, row) {
$('input[st-search="'+row.stSearch+'"]').val(row.value);
});
Прямо сейчас я зацикливаюсь на том, что делает Angular. Я пытаюсь последовать предложению, чтобы попытаться сделать "все" в Angular без JQuery ( "Мышление в AngularJS", если у меня есть опыт работы с jQuery?), Но я не уверен, как лучше всего подойти к этому. Можете ли вы использовать $scope.$ Watch для общего просмотра множества элементов на основе селектора CSS (я могу найти только примеры, чтобы сделать это для конкретной модели)? Будет ли это лучше всего сделать с декоратором на каждом входе или родительском элемент? Я действительно не уверен, куда идти отсюда!
1 ответ
Ну, это не очень хорошее решение, но оно делает то, что мне нужно, комбинируя Angular с jQuery! Я решил использовать атрибут / директиву (st-search-cookie) для тега tr, который содержит поля поиска. Например:
<tr st-search-cookie>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
Вы можете опционально определить имя cookie и имя коллекции в директиве. В противном случае он использует хэш md5 всех доступных полей поиска в качестве имени коллекции. Идея заключается в том, что у вас есть один файл cookie, который может иметь коллекции для множества разных таблиц, а не множество файлов cookie (т. Е. Иметь один файл для каждой таблицы).
В любом случае, он автоматически находит стандартные поля ввода st-search (input [st-search]), а также любые с атрибутом * предиката (input [предикат]), которые обычно используются при создании пользовательских директив поиска.
Надеюсь, кто-то найдет это полезным или, что еще лучше, улучшит его!
(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);