ryanzec
ryanzec

Reputation: 28040

Parent directive transclusion does not work when content generated by child directive

I have two directives where the outer one is using transclusion. It should be attaching an attr to content that is inside the outer directive that is being generated by the inner directive however the attach attr does not seem to work:

plunker link 1

I am also getting the error:

TypeError: Cannot read property 'childNodes' of undefined

Which I assume has something to do with this.

If I don't use the inner directive and manually place the html in the outer directive that would be generated by the inner directive, everything works fine:

plunker link 2

The actually use case here is that I have two directives. One of them in a search query component that lets you build a search with specific syntax and validates it as you type letting you know if you have any syntax errors. I also have a extend text component which one of the features in an auto complete. Both of these components work fine separately however I am try to combine the functionality so that I can have a query builder with auto complete. I am running into the issue that none of the functionality of the extend text component is actually being added to the search query component (just like none of the functionality of outer directive is being added to inner directive here).

Is there anything I am doing wrong here (why am I getting that childNodes error)? Is this not the way to combine functionality of two directives that each have there own templates?

NOTE

UPDATE

Based on @zeroflagL suggestion, I removed the used on $compile however it still does not work

plunker link 3

The input does have the ng-click and there are no more javascript error however clicking the input does not trigger the alert.

Upvotes: 0

Views: 185

Answers (1)

a better oliver
a better oliver

Reputation: 26828

element.find('.outer-inputs').append($compile(copyElement)($scope));

You don't need $compile.

compile: function(element, attributes, transclude) {

The use of transclude in the compile function is deprecated.

Working example:

compile: function(element, attributes) {
          return {
            pre: function($scope, element, attributes) {
            },
            post: function($scope, element, attributes, ctrl, transclude) {
              transclude($scope, function(clone) {
                var copyElement = clone.filter('.outer-copy');

                copyElement.find('input').on('click', function() {
                  focus();
                  //$scope.$apply();  only if you change the model.
                });

                element.find('.outer-inputs').append(copyElement);
              });

Not related to the problem: The directive's controller is useless, as it has no methods. You can add focus() to the scope directly in your directive.

Edit

In your example you compile an element that already has been compiled and is still under construction (the post-link phase). That's not going to work. You effectively try to change your inner directive. But either the directives are idependent, then outer shouldn't mess with inner, or they are aware of each other. In that case there's no need for hacking the DOM as they could interoperate in other ways.

Upvotes: 0

Related Questions