Angular directives, compositeLinkFn(): node is 'undefined'

249 views
Skip to first unread message

Mikhail Nikitin

unread,
Sep 15, 2015, 2:48:55 AM9/15/15
to AngularJS
I have a trouble with compositeLinkFn()
In the last line of it, "childLinkFn(scope, node.childNodes,...", node is 'undefined'. Why could this happen?

Background: I'm doing a custom directive with transclusion 'element'. The simple setup in plunkr works, but the more complex real project does not, I'm trying to debug it.

Sander Elias

unread,
Sep 16, 2015, 1:01:32 AM9/16/15
to AngularJS
Hi Mikhail,

It's really hard to help you here without a way to reproduce your issue. If a plunk works and the real code doesn't there is a significant difference somewhere. (duh...). For myself I found a lot of solutions while trying to reproduce an problem in a plunk. A lot of, "Ok, I'm going to build this plunk to file a issue", turned into, "uhoh, what was I thinking..." ;)

Regards
Sander

Mikhail Nikitin

unread,
Sep 16, 2015, 1:53:51 AM9/16/15
to ang...@googlegroups.com
I tried to reproduce it in Plnkr, but got another error: "Cannot read property 'insertBefore' of null". You can see this here: http://plnkr.co/edit/Az01nG?p=preview (there were some troubles when saving, so the title isn't accurate). The error pops up in the console if one removes the "ng-if" attribute from <tbody>. This might be related to my issue, but I can't figure out what "ng-if" does, that my directive doesn't.

--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/BqWfGESgSQI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Sander Elias

unread,
Sep 16, 2015, 2:00:37 AM9/16/15
to AngularJS
ngIf creates a new scope. Also, takes out the DOM and puts it back in once its expression becomes true. this even happens if you put in 'true'
(wrote this before looking into your code, might help you already.)

Regards
Sander

Sander Elias

unread,
Sep 16, 2015, 2:02:57 AM9/16/15
to AngularJS
And in addition to my previous answer, after a first glance over your code, and here is your issue I believe, ngIf defers the execution of your directive to the next digest cycle.

Mikhail Nikitin

unread,
Sep 16, 2015, 2:07:41 AM9/16/15
to ang...@googlegroups.com
Yes, ngIf sets up a $watch, I recon. I could try using angular.$apply... But I wonder why it is so.

On Wed, Sep 16, 2015 at 8:02 AM, Sander Elias <sande...@gmail.com> wrote:
And in addition to my previous answer, after a first glance over your code, and here is your issue I believe, ngIf defers the execution of your directive to the next digest cycle.

--

Mikhail Nikitin

unread,
Sep 16, 2015, 2:22:54 AM9/16/15
to ang...@googlegroups.com
$apply() and $watch() are not working. And by the way, ngIf does not make an isolated scope.

Sander Elias

unread,
Sep 16, 2015, 2:24:12 AM9/16/15
to AngularJS
The $watch isn't the relevant part here. The fact that your code gets executed in the next $digest cycle is!

Mikhail Nikitin

unread,
Sep 16, 2015, 2:26:47 AM9/16/15
to ang...@googlegroups.com
Then I obviously miss something... I fail to see from ngIf code, how does it defer the execution, and how I can do the same.

From: Sander Elias
Sent: ‎16/‎09/‎2015 08:24
To: AngularJS
Subject: Re: [AngularJS] Re: Angular directives, compositeLinkFn(): node is'undefined'

The $watch isn't the relevant part here. The fact that your code gets executed in the next $digest cycle is!

--

Sander Elias

unread,
Sep 16, 2015, 2:39:26 AM9/16/15
to AngularJS
Easiest way to defer code to next cycle is using `$timeout(codeIwantInNextCyle,0)` That is something that just is needed sometimes. Usually when setting up stuff in 1 element, that you then need in another element. This is indeed a code smell, and you should hand over the data more explicit, so this crux isn't needed at all. But as I said, sometimes you just have to wait a bit.
I don't have time to figure out what is the exact reason it needs to be deferred in your use-case tough.  

Mikhail Nikitin

unread,
Sep 16, 2015, 2:43:32 AM9/16/15
to ang...@googlegroups.com
Thanks for a hint. Alas, this doesn't help it either. If I knew the reason for that error message, I might have been able to do something about it, or at least ask a more focused questions :-)  Maybe, someone else could tip in?..

On Wed, Sep 16, 2015 at 8:39 AM, Sander Elias <sande...@gmail.com> wrote:
Easiest way to defer code to next cycle is using `$timeout(codeIwantInNextCyle,0)` That is something that just is needed sometimes. Usually when setting up stuff in 1 element, that you then need in another element. This is indeed a code smell, and you should hand over the data more explicit, so this crux isn't needed at all. But as I said, sometimes you just have to wait a bit.
I don't have time to figure out what is the exact reason it needs to be deferred in your use-case tough.  

--

Sander Elias

unread,
Sep 16, 2015, 2:46:01 AM9/16/15
to AngularJS
Oh, I misunderstood your question, you wanted to know how the ngIf does the deferring..

Well, it's a side-effect from the watch. When the ngIf is executed the link function gets executed. During this time the only thing it does is setting up a watch with a callback.
This callback is not executed right away, but on the next $digest cycle.

Regards
Sander

Mikhail Nikitin

unread,
Sep 16, 2015, 2:50:43 AM9/16/15
to ang...@googlegroups.com
Thanks. This is what I tried to achieve setting my "transclude" call inside a $watch - that didn't help.
On the other hand, I also created a "myIf" directive without a watch, and it still eliminates the error, so it might not be $digest after all.

--

Sander Elias

unread,
Sep 16, 2015, 2:59:15 AM9/16/15
to AngularJS
$watch isn't the only thing that causes this. there are many more constructs inside angular that use similar means. A lot of stuff around/including transclude does this too. (not limited to that either ;))

Sander Elias

unread,
Sep 16, 2015, 3:03:48 AM9/16/15
to AngularJS
You combine a number of directives that all manipulate/rely on the DOM. So executing them in the wrong order will cause your problem. To find the root cause, you have to go over each and everyone using a debugger. That takes a while. Injecting a $timeout is a crux, but it might save you quite some hours. Oh, and after that debugging, changes are, that $timeout is the right solution after all. (aside from fixing your 3rth party directives.)

Mikhail Nikitin

unread,
Sep 16, 2015, 3:11:45 AM9/16/15
to ang...@googlegroups.com
I have tried $timeout to no avail - see the Plnkr. I tried to debug, but it's hard to debug inside Angular code. I see unfortunately no ways to proceed at the moment...

On Wed, Sep 16, 2015 at 9:03 AM, Sander Elias <sande...@gmail.com> wrote:
You combine a number of directives that all manipulate/rely on the DOM. So executing them in the wrong order will cause your problem. To find the root cause, you have to go over each and everyone using a debugger. That takes a while. Injecting a $timeout is a crux, but it might save you quite some hours. Oh, and after that debugging, changes are, that $timeout is the right solution after all. (aside from fixing your 3rth party directives.)

--
Reply all
Reply to author
Forward
0 new messages