60307

does angular create new DOM tree after compile phase or continue working with original modified DOM?

Question:

For example, I have the following HTML:

<div dir-parent> <div dir-child1></div> </div>

During compilation phase directive dirParent will receive template DOM element that has inside of it the div with a dirChild1 directive. If I don't change this html inside dirParent's compile function, then compile function is then called for dirChild1 directive. However, if I remove <div dir-child1="" some-child1-attr></div> inside dirParent's compile function, then angular continues processing this <em>modified</em> DOM that no longer has a div with dir-child1 directive and so compile function for dir-child1 directive is never executed.

I assumed that once angular is done executing compile functions it builds new DOM from html <em>modified</em> during compile functions. Is this assumption correct? This <em>modified</em> DOM seems to be referred as <em>instance</em> DOM elements and is available during pre-link phase, so I assume that this is the phase when angular constructs instance elements DOM tree.

Answer1:

I've spent 3 hours investigating Angular's source code (it's written in so hard to read manner) and found the answer to my question. Angular doesn't distinguish between template and instance elements inside, it works with the same tree it has when it begins compiling. Here is the essence of the source code that demonstrates that:

var element = $("body"); compile(element)($rootScope); function compile(DOMElementsTree) { var compositeLinkFn = compileNodes(DOMElementsTree); return function publicLinkFn(scope) { var $linkNode = DOMElementsTree; compositeLinkFn(scope, $linkNode); return $linkNode; } } function compileNodes(nodesList) { var linkFns = []; nodesList.forEach(function (node) { var nodeLinkFn = applyDirectivesToNode(node); var childNodes = nodesList.childNodes; var childLinkFn = !!childNodes.length ? compileNodes(childNodes) : null; if (nodeLinkFn || childLinkFn) { linkFns.push(i, nodeLinkFn, childLinkFn); } }); return function compositeLinkFn(scope, nodeList) { linkFns.forEach(function (linkFn) { var nodeLinkFn = linkFn[1]; var childNodeLinkFn = linkFn[2]; if (nodeLinkFn) { nodeLinkFn(childLinkFn, scope, nodeList); } else if (childNodeLinkFn) { childLinkFn(scope, nodeList) } }); } } function applyDirectivesToNode() { // this is where compile functions of all directives on a node are executed } function nodeLinkFn() { // here pre link and post link functions are executed } function childLinkFn() { // here pre link and post link functions are executed }

You can see that applyDirectivesToNode which executes compile functions of a directive doesn't return any new DOM node, instead it modifies DOMElementsTree that it receives by references and compositeLinkFn continues working with this DOM instance.

Initially I had this piece of sample code in my question taking <a href="https://docs.angularjs.org/guide/compiler#how-directives-are-compiled" rel="nofollow">from here</a>:

var $compile = ...; // injected into your code var scope = ...; var parent = ...; // DOM element where the compiled template can be appended var html = '<div ng-bind="exp"></div>'; // Step 1: parse HTML into DOM element var template = angular.element(html); // Step 2: compile the template var linkFn = $compile(template); // Step 3: link the compiled template with the scope. var element = linkFn(scope); // Step 4: Append to DOM (optional) parent.appendChild(element);

So in this extract the last step deals with the result of the publicLinkFn function, namely $linkNode in my code above.

Answer2:

The DOM element is indeed created during step1, however it is only available in the browser memory but not reflected in the actual page DOM.

Since the element has been created from Javascript (var html = ...) once it is compiled and linked, you need to put it back to the page using append so the user can actually see and interact with it.

<strong>Update</strong> I don't understand what you are asking exactly, but I don't think you will find an answer on StackOverflow. What you need is a forum or more lecture about the internal functionning of AngularJS. I highly recommend you to read this article: <a href="http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/" rel="nofollow">http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/</a>

<strong>Update2</strong> From my understanding (and accoding to the article cited above), Angular will first compile the template from dir-parent and then compile its children <em>using that same template</em>. If you have modified this template during the top compile phase, for instance by removing dir-child1, then indeed there is nothing else to compile and Angular will then proceed with the pre-link and finally post-link.

Recommend

  • why when we write \\n in the file it converts into \\r\\n combination?
  • Java library to escape/clean XML?
  • remove Niqqud from string in javascript
  • SocketChannel: java.io.IOException: An existing connection was forcibly closed by the remote host
  • Newtonsoft inline formatting for subelement while serializing
  • Why is RAM in powers of 2?
  • Visual basic auto imports namespaces
  • WPF Listbox commands
  • How to access meteor package name inside package?
  • JSR-330 support in Picocontainer : @Inject … @Named(\"xxx)
  • How to get latest version of a artifact on Bintray using JSONP
  • Tell Git to stop prompting me for conflicts when none really exist?
  • Insert new calendar with SyncAdapter- Calendar API Android
  • Ensure fsync did its job
  • Content-Length header not returned from Pylons response
  • Ajax Loaded meta Tags
  • Xamarin Forms - UWP Fonts
  • Counter field in MS Access, how to generate?
  • How to recover from a Spring Social ExpiredAuthorizationException
  • ILMerge & Keep Assembly Name
  • Arrow is showed instead of the material design version hamburger icon. Why doesn't syncState in
  • Javascript + PHP Encryption with pidCrypt
  • Websockets service method fails during R startup
  • Large data - storage and query
  • Jquery - Jquery Wysiwyg return html as a string
  • WOWZA + RTMP + HTML5 Playback?
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • Arrays break string types in Julia
  • InvalidAuthenticityToken between subdomains when logging in with Rails app
  • SQL merge duplicate rows and join values that are different
  • WPF Applying a trigger on binding failure
  • Acquiring multiple attributes from .xml file in c#
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Java static initializers and reflection
  • LevelDB C iterator
  • How can I remove ASP.NET Designer.cs files?
  • Can't mass-assign protected attributes when import data from csv file
  • How can i traverse a binary tree from right to left in java?
  • java string with new operator and a literal