【问题标题】:Custom directive - Illegal use of ngTransclude directive in the template自定义指令 - 在模板中非法使用 ngTransclude 指令
【发布时间】:2018-12-11 02:05:52
【问题描述】:

我使用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-transcludeiElement.removeAttr("ng-transclude");,这导致按钮内的文本消失了。

这种没有模板的指令风格有什么解决办法?

【问题讨论】:

    标签: angularjs angular-directive angularjs-ng-transclude


    【解决方案1】:

    正如this solution 所说,这是一个时间问题。

    简单的解决方案实际上是删除ng-transclude 属性,因为我的属性指令中显然不需要它。

    iElement.removeAttr("ng-transclude");
    $compile(iElement)(scope);
    

    然后从父级按钮本身中删除了ng-transclude 属性(不理想 - 它删除了按钮上的文本)。这是一个时间问题,因为它在按钮加载之前运行。

    为了让它在加载按钮后运行,我只是将compile 中的pre 更改为post

    例如..

    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
        };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 2016-09-22
      • 2018-01-09
      • 2012-04-28
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多