简体   繁体   中英

How to define an angular directive inside an angular directive's link function?

I want to create an angular directive inside of a link function, however; the directive created is not able to be compiled.

See this JSFiddle: http://jsfiddle.net/v47uvsj5/5/

Uncommenting this directive in the global space works as expected.

app.directive('test', function () {
    return {
        templateUrl: 'myform', // wraps script tag with id 'myform'
        restrict: 'E',
        require: "^mydir",
        replace: true,
        scope: {
        },
        link: function (scope, element, attrs, mydirCtrl) {
            scope.remove = function () {
                element.remove();
                mydirCtrl.remove();
            }
        }
    }
});

But the exact same code inside the link function fails.

The reason I want to do this is because I want the user (who is going to be myself) to be able to provide only a script tag's id via an id attribute to my main directive which will in turn create a 'wrapper' directive with a 'remove' method. This way, in the script tag, all one needs to do is implement the 'remove'.

Check out this fiddle:

http://jsfiddle.net/v47uvsj5/8/

What I did in this fiddle was daisy chain your directives, which is the correct thing to do. When your app runs, it does a binding of each of your directive and builds your html as it's being compiled, then it links events to it. Links and compilation happen after binding all directives to the DOM.

So <test></test> becomes <div></div> if you give it a template. If there is no template, nothing really builds your directive against the DOM, it just becomes empty, but you can still run a jquery script if you want.

Think of it like this, when your app loads up, it registers all the directives to be binded with the associated templates. Afterwards, the app then "compiles" those directives by binding any kind of events to the newly established DOM. At this point, if no directives are registered during app load, the compile function ignores it. In your case, you tried to bind the 'test' directive after the app load, and during the compilation.

This mechanism is analogous to how jquery's "on" works. When you do a "click" event on an already loaded DOM element, this fires up. But when you load html AFTER the DOM is finished, nothing works unless you use "on".

To be fair, the developers of angular did mention how there's a steep learning curve for handling directions, and will be revised to make it much easier in 2.0. You can read about it in this blog here: Angular-2.0

Anyways,

This is how your html should look like:

<mydir><test></test></mydir>

and this is how you daisy chain:

var app = angular.module('app', []);

app.directive('mydir', function ($compile, $templateCache) {
    return {
        template: '',
        restrict: 'E',
        controller: function () {
           console.log("got it!");
        }
    }
}).directive('test', function () {
    return {
        templateUrl: 'myform',
        restrict: 'E',
        require: "^mydir",
        replace: true,
        scope: {
        },
        link: function (scope, element, attrs, mydirCtrl) {
            scope.remove = function () {
                element.remove();
                mydirCtrl.remove();
            }
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM