Tuesday, March 19, 2013

How to handle DOM updates in AngularJS Directives in "link"

AngularJS directives are great. They provide a really wonderful mechnism "to teach HTML new tricks". But apparently there is no predefined mechanism for doing your DOM manipulation after the template has been loaded, cloned and transformed and rendered. Today I found a workaround for that.

var myModule = angular.module(myModule', []);
    myModule.directive('myDirective', function () {
        return {
            templateUrl: 'partials/timeline.html',
            link: function postLink(elem, attrs, transclude) {
                    // This code will run after
                    // templateUrl has been loaded and cloned
            }
        };
    );

The problem is divided in two steps, that must be handled each: The function "link" is called after the template has been cloned. This does not include any DOM manipulations that happen after this cloning, triggered by directives ng-repeat or ng-view. If you want to start your DOM manipulation after these directives have been handled by AngularJS (i.e. the DOM has been manipulated), you will need a setTimeout, or better the $timeout function from AngularJS.

So now you will get this code.
var myModule = angular.module(myModule', []);
    myModule.directive('myDirective', function ($timeout) {
        return {
            templateUrl: 'partials/timeline.html',
            link: function postLink(elem, attrs, transclude) {
                $timeout(function () {
                    // This code will run after
                    // templateUrl has been loaded, cloned
                    // and transformed by directives.
                }, 0);
            }
        };
    );
Yeah, that's better. But wait, we're not done yet. What if you want you want to do transformations of the DOM based on the positions of the newly rendered elements? Getting the position, offset, height, width of the newly created elements are not guaranteed to provide the correct values, because the browser had not enough time to render and layout those elements. The hack is to further delay these operations.
var myModule = angular.module(myModule', []);
    myModule.directive('myDirective', function ($timeout) {
        return {
            templateUrl: 'partials/timeline.html',
            link: function postLink(elem, attrs, transclude) {
                $timeout(function () {
                    $timeout(function () {
                        // This code will run after
                        // templateUrl has been loaded, cloned
                        // and transformed by directives.
                        // and properly rendered by the browser
                    }, 0);
                }, 0);
            }
        };
    );
If you wonder, why a timeout of 0 really helps, here's a great explanation by John Resig.

42 comments:

  1. I had a similar problem. I needed to search in element's inner DOM for certain selector.
    When I used $(element) it returned empty array.
    When I tried your solution with nested $timeout it worked, but I did not like it.
    Finally I tried angular.element(elem).find(selector) and this worked. I did not have to use $timeout.

    ReplyDelete
  2. Hi David,

    I have a similar problem. Can you please give me an example to use this.
    Thanks in advance.

    ReplyDelete
  3. What should be the right solution in your opinion?

    ReplyDelete
  4. Ugly or not, it worked like a charm and I'll leave like so.

    After hours trying to find a nice solution here.

    I had to use it combined with a third-party core that I didn't want to refactor.

    Thanks a lot for sharing!

    ReplyDelete
  5. Great solution. When nothing solved my issue of default focus to an element, this code worked as a charm.

    ReplyDelete
  6. Instead of two timeouts, would it be better if we put a single timeout with some delays greater than 0?

    ReplyDelete
    Replies
    1. It actually would work if the timeout is long enough.
      The problem is indeed, finding the right value so that this would always work, even on the slowest mobile device, but also work really fast on some high-end desktop computer. So I decided not to slowing down desktop computer users and risking of my code not to work correctly and went with the double $timeout.

      Delete
  7. Thanks a lot .
    I have same type of issue
    and i searched a lot on web but i din get any usefull link
    later i found your link and i apply as you mention then it works nice.
    Good Job dear
    thank you so much...

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. I have some CSS transitions running during rerndering...the double timeouts do not seem to take care of this fact, and the code is run before/during the transitions

    ReplyDelete
    Replies
    1. Are your transitions defined to take longer than 0 s? If they ware, you should consider taking a timeout delay of a value greater than 0 for the innermost timeout.

      Delete
  10. I think the content covered in the blog is quite impressive and brilliantly conveyed. Good job and great efforts. Keep it up.
    Angularjs developer

    ReplyDelete
  11. It is nice blog Thank you provide important information and i am searching for same information to save my time AngularJS5 Online Training

    ReplyDelete
  12. Your article was too good I really appreciate it. I am working for BR Softech it is one of the best angularjs development company. But according to time, there is a lot of changes coming so I request to you please update it regularly & Keep it up.

    ReplyDelete
  13. Colour Moon Technologies has the best and suitable solution for you. As we know Lunch Box Delivery is a very helpful to every Employees who was carving for the Neat, Hygienic and Homely food which is no where.

    So, Now you can start your own Online business by Design a website & Mobile App and Show case your lunch box items you offer, and the prices for each. Make it easy way to customers to place their orders online as well as to let you know whether they can give an dietary restrictions.

    So what are you waiting for, Let's start up the Business plan and execute in a smart way by promoting through online. Join your hands with Colour Moon Technologies, the Experts in Developing Websites, Mobiles Apps and Gaming Apps with 10+ years of Experience.

    https://bit.ly/2XY6rXw

    ReplyDelete
  14. Dengan begitu anda sebagai pemain juga harus pandai memaksimalkan waktu yang ada dengan sebaik mungkin
    asikqq
    dewaqq
    sumoqq
    interqq
    pionpoker
    bandar ceme terpercaya
    hobiqq
    paito warna terlengkap
    bocoran sgp

    ReplyDelete
  15. I am impressed with your article , i am looking for angular js article but i also know a game development company who also write same article.

    ReplyDelete
  16. ExpressTech Softwares – Top Angularjs Development company in India, offers best AngularJS development services for mobile / website application at affordable price. +91-9806724185 or Contact@expresstechsoftwares.com

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. Hiiii...Thanks for sharing Great info...Nice post...Keep move on...
    Angular JS Training in Hyderabad

    ReplyDelete
  19. This comment has been removed by the author.

    ReplyDelete
  20. Such a useful and great information for me about handling DOM updates in AngularJS.
    To Hire Angularjs Developers visit Mobiwebtech.com

    ReplyDelete
  21. Turning out to be among one of the most favorable places to outsource projects, India is leading its way. There is no doubt that Indian app development companies are rated in the top development companies. If you also want to hire Indian app developers, you can rely on the list of top indian app development companies 2020.
    1. OpenXcell
    2. The NineHertz
    3. Indian App Developer

    ReplyDelete
  22. Dream11 is one of the most popular and trending fantasy app in the Indian subcontinent. It has emerged to become one of the biggest names in the fantasy sports genre of mobile applications. This application is popular because it allows the participants to win some quick money. If the participants have the right knowledge and skills, they can win a significant amount of money from each game they play. Are you wondering that how to make app like Dream11? However, you must understand that it is not an easy task to start a fantasy app development project.

    ReplyDelete
  23. Nice information shared. Very helpful for developers to get knowledge from here. Thanks for share. Sales CRM Software

    ReplyDelete
  24. Thanks for sharing this informative post with us. CRM
    The Best CRM that helps your business to grow Smarter, Better and Faster.

    ReplyDelete
  25. Thanks so much for sharing your wisdom and experience.sales outsourse

    ReplyDelete
  26. It’s Great site sir,I am regularly following your site thanks for sharing with us.IT services

    ReplyDelete
  27. Ah,so beautiful and wonderful post!An opportunity to read a fantastic and imaginary blogs.It gives me lots of pleasure and interest.Thanks for sharing.
    Data Science Training In Chennai

    Data Science Course In Chennai


    ReplyDelete
  28. Our expert pharmacy app developers are able to create the best user friendly medicine delivery app that will make your customers lives easier and take your business to a new level.
    Pharmacy App Development

    ReplyDelete
  29. Thanks for sharing this wonderful content.it's very useful to us. I gained a lot of information, the way you have clearly explained is really fantastic. Thanks a lot for this blog.

    Hire Dedicated Angularjs Developers

    ReplyDelete
  30. I am really happy to say it’s an amazing post to read. I learn new information from your article, you are doing a great job. Keep it up

    Hire AngularJS Developer

    ReplyDelete
  31. Pharma Coders provides readymade and customized Online Pharmacy App Development for different pharma business types.

    ReplyDelete