我使用this directive来防止双击。
我的代码:
export function cbOneClickOnly($parse, $compile): ng.IDirective {
"use strict";
return {
compile: function(tElement: ng.IAugmentedJQuery, tAttrs: ng.IAttributes) {
if (tAttrs.ngClick) {
throw "Cannot have both ng-click and cb-one-click-only on an element";
}
tElement.attr("ng-click", "oneClick($event)");
tElement.attr("ng-dblclick", "dblClickStopper($event)");
tElement.removeAttr("cb-one-click-only");
let theClickFunctionToRun = $parse(tAttrs["cbOneClickOnly"]);
return {
pre: function(scope: ng.IScope, iElement: ng.IAugmentedJQuery) {
let hasBeenClicked: boolean = false;
scope.oneClick = function(event: Event) {
if (hasBeenClicked) {
throw "Already clicked";
}
hasBeenClicked = true;
$(event.srcElement).attr("disabled", "disabled");
theClickFunctionToRun(scope, { $event: event });
return true;
};
scope.dblClickStopper = function(event: Event) {
event.preventDefault();
throw "Double click not allowed!";
};
$compile(iElement)(scope);
}
};
},
restrict: "A",
scope: true
};
}
然后将其添加到应用中,如下所示:
angular.module(moduleId, []).directive("cbOneClickOnly", ["$parse", "$compile", cbOneClickOnly])
,其用法如下:
<md-button class="md-accent" cb-one-click-only="$ctrl.itemSaveClicked(item)">
Save
</md-button>
但是我得到这个错误:
> Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in
> the template! No parent directive that requires a transclusion found.
> Element: <!-- ngIf: $ctrl.isSaveDisplayed() -->
> https://errors.angularjs.org/1.7.5/ngTransclude/orphan?p0=%3C!--%20ngIf%3A%20%24ctrl.isSaveDisplayed()%20--%3E
> at eval (angular.js:138)
> at Object.ngTranscludePostLink (angular.js:34687)
> at eval (angular.js:1365)
> at invokeLinkFn (angular.js:11235)
> at nodeLinkFn (angular.js:10554)
> at compositeLinkFn (angular.js:9801)
> at publicLinkFn (angular.js:9666)
> at lazyCompilation (angular.js:10080)
> at boundTranscludeFn (angular.js:9844)
> at controllersBoundTransclude (angular.js:10604) "<!-- ngIf: $ctrl.isSaveDisplayed() -->"
This solution解决了我的问题,但是在具有html的指令上,而我的却没有。
我手动删除了ng-transclude
,就像这样:iElement.removeAttr("ng-transclude");
,这导致按钮内的文本消失了。
这种没有模板的指令样式的解决方案是什么?
答案 0 :(得分:0)
this solution说,这是一个时间问题。
简单的解决方案实际上是删除ng-transclude
属性,因为我的attribute指令显然不需要它。
iElement.removeAttr("ng-transclude");
$compile(iElement)(scope);
然后从父项(按钮本身)中删除了ng-transclude
属性(不理想-它删除了按钮上的文本)。这是一个计时问题,因为它是在加载按钮之前运行的。
要使其在按钮加载后运行,我只是在pre
内将post
更改为compile
。
例如。
return {
pre: function(scope: ng.IScope, iElement: ng.IAugmentedJQuery) {
let hasBeenClicked: boolean = false;...
成为
return {
post: function(scope: ng.IScope, iElement: ng.IAugmentedJQuery) {
let hasBeenClicked: boolean = false;...
最终解决方案:
export function cbOneClickOnly($parse, $compile): ng.IDirective {
"use strict";
return {
compile: function(tElement: ng.IAugmentedJQuery, tAttrs: ng.IAttributes) {
delete tAttrs.ngTransclude;
if (tAttrs.ngClick) {
throw "Cannot have both ng-click and cb-one-click-only on an element";
}
tElement.attr("ng-click", "oneClick($event)");
tElement.attr("ng-dblclick", "dblClickStopper($event)");
tElement.removeAttr("cb-one-click-only");
let theClickFunctionToRun = $parse(tAttrs["cbOneClickOnly"]);
return {
post: function(scope: ng.IScope, iElement: ng.IAugmentedJQuery) {
let hasBeenClicked: boolean = false;
scope.oneClick = function(event: Event) {
if (hasBeenClicked) {
throw "Already clicked";
}
hasBeenClicked = true;
$(event.srcElement).attr("disabled", "disabled");
theClickFunctionToRun(scope, { $event: event });
return true;
};
scope.dblClickStopper = function(event: Event) {
event.preventDefault();
throw "Double click not allowed!";
};
iElement.removeAttr("ng-transclude");
$compile(iElement)(scope);
}
};
},
restrict: "A",
scope: true
};
}