Watch/Update AngularJS 中的一组输入的正确方法
Proper way to Watch/Update a group of inputs in AngularJS
在使用 JQuery 多年后,我目前正在学习 AngularJS。现在,我正在考虑实现智能表 (http://lorenzofox3.github.io/smart-table-website/),并希望能够自动将搜索查询保存到 cookie 中,以便我可以在用户 return 时重新加载它们。理想情况下,我希望有一种通用的方法来执行此操作,以便我可以通过使用单个指令或 DI 来重新使用代码。
在JQuery的世界里,我会这样做:
HTML:由 st-search 定义的单个搜索条目,但我们可以有 n-这些都具有唯一 ID 的数量。
<tr>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
"onChange" Javascript:监听所有字段更新,这样我就可以调用我的存储服务(可能是 cookie),而不是发出警报为此 table.
保存更新的搜索参数
$('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 中执行 "everything" 而没有 JQuery ("Thinking in AngularJS" if I have a jQuery background?),但我不确定如何最好地解决这个问题。您可以使用 $scope.$watch 来根据 CSS 选择器一般地监视很多元素吗(我只能找到针对特定模型执行此操作的示例)?最好在每个输入或父 元素上使用装饰器来完成吗?我真的不知道从这里去哪里!
好吧,这不是一个很好的解决方案,但它确实通过将 Angular 与 jQuery 组合来满足我的需要!我决定在包含搜索字段的 tr 标签上使用 attribute/directive (st-search-cookie)。例如:
<tr st-search-cookie>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
您可以选择在指令中定义 cookie-name 和 collection-name。否则,它使用所有可用搜索字段的 md5 散列作为集合名称。这个想法是你有一个单一的 cookie,它可以有许多不同的 table 的集合,而不是有很多 cookie(即每个 table 都有一个)。
无论如何,这会自动找到默认的 st-search 输入框 (input[st-search]) 以及任何带有*predicate' 属性 (input[predicate]),在制作自定义搜索指令时常用。
希望其他人会发现它有用,或者更好地改进它!
(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);
在使用 JQuery 多年后,我目前正在学习 AngularJS。现在,我正在考虑实现智能表 (http://lorenzofox3.github.io/smart-table-website/),并希望能够自动将搜索查询保存到 cookie 中,以便我可以在用户 return 时重新加载它们。理想情况下,我希望有一种通用的方法来执行此操作,以便我可以通过使用单个指令或 DI 来重新使用代码。
在JQuery的世界里,我会这样做:
HTML:由 st-search 定义的单个搜索条目,但我们可以有 n-这些都具有唯一 ID 的数量。
<tr>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
"onChange" Javascript:监听所有字段更新,这样我就可以调用我的存储服务(可能是 cookie),而不是发出警报为此 table.
保存更新的搜索参数$('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 中执行 "everything" 而没有 JQuery ("Thinking in AngularJS" if I have a jQuery background?),但我不确定如何最好地解决这个问题。您可以使用 $scope.$watch 来根据 CSS 选择器一般地监视很多元素吗(我只能找到针对特定模型执行此操作的示例)?最好在每个输入或父 元素上使用装饰器来完成吗?我真的不知道从这里去哪里!
好吧,这不是一个很好的解决方案,但它确实通过将 Angular 与 jQuery 组合来满足我的需要!我决定在包含搜索字段的 tr 标签上使用 attribute/directive (st-search-cookie)。例如:
<tr st-search-cookie>
<th><input st-search="id" class="form-control" placeholder="Search by ID" type="number"/></th>
</tr>
您可以选择在指令中定义 cookie-name 和 collection-name。否则,它使用所有可用搜索字段的 md5 散列作为集合名称。这个想法是你有一个单一的 cookie,它可以有许多不同的 table 的集合,而不是有很多 cookie(即每个 table 都有一个)。
无论如何,这会自动找到默认的 st-search 输入框 (input[st-search]) 以及任何带有*predicate' 属性 (input[predicate]),在制作自定义搜索指令时常用。
希望其他人会发现它有用,或者更好地改进它!
(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);