Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - How do I avoid using $timeout to wait for an element to be created?

Here is the idea:

So I am trying to use an external library function to create some manipulation in the DOM in one of my controllers that my ng-repeat is connected to.

Newest jsFiddle working but ...

http://jsfiddle.net/GeorgiAngelov/KRbdL/150/

So basically I got it to work with @BrandonTilley's help but I am trying to avoid using $timeout as I don't think that it is a viable solution but a hack.

New fiddle with the help of @BrandonTilley

added onload listener and also I am trying to get the new element or its parent by getElementById but all it returns is NULL.

http://jsfiddle.net/GeorgiAngelov/KRbdL/143/

The problem is the following: I am calling that external function in my controller that adds elements to the ng-repeat array , which in term adds the new elements to the DOM. However, when I am inside the controller, the element does not exist yet, even though I have added it to the array.

How can I bound an external function to be called once the element has actually been appended to the DOM, rather than when it was actually added to the array that controls the ng-repeat?

The problem comes is that I have template 1 calling template 2, then template 2 calls template3 and then template3 calls back template 2, and I want to connect an element from template3 into template2 once template3's finishes rendering template2.

I created a directive that is linked to template3 and I used the $last property but it is still not working because template3 loads but I do not know when template2 finishes loading.Furthermore, the element.ready() does not even fire up. I also tried hacking it around with $timeout and removing element.ready, but it still gave me the error that the child element did not exist yet. I do not want to use $timeout and so I am looking for a more functional solution to my problem.

Also, I tried calling the jsPlumb library when I call the function to create a new firstlevel element but it gives parentNode undefined. I commented it out in addChild function .

Directive that is used in template 3 on the ng-repeat ng-include=template2

app.directive('vectorDrawDirective', function($timeout) {
    return function($scope, element, attrs) {
        //angular.element(element).css('color','blue');
        if ($scope.$last === true) {
            element.ready(function() {
            jsPlumb.connect({
                    source: $scope.firstlevel.parent_id,
                    target: $scope.firstlevel.id,
                });
                jsPlumb.repaintEverything();    
        })
        }
    }
});

Here is a diagram I did to help you visualize what I am trying to acomplish ( look at the text on the top right corner )

enter image description here

like image 366
Georgi Angelov Avatar asked Jul 12 '13 13:07

Georgi Angelov


People also ask

What is the ‘$ timeout’ service of AngularJS?

This article will deal with the ‘$timeout’ service of AngularJS. This ‘$timeout’ service of AngularJS is functionally similar to the ‘window.setTimeout’ object of vanilla JavaScript. This service allows the developer to set some time delay before the execution of the function.

How do I call a method again and again in AngularJS?

In your projects you might want to call a particular method again and again after a particular interval of time, it can be used in those cases where we need to refresh a particular control so that new data can be seen. It can be done using the $timeout directive of AngularJS.

What is the wrapper for window timeout in angular?

Overview AngularJS's wrapper for window.setTimeout. The fnfunction is wrapped into a try/catch block and delegates any exceptions to $exceptionHandlerservice. The return value of calling $timeoutis a promise, which will be resolved when the delay has passed and the timeout function, if provided, is executed.

What is the difference between $delay and pass in angular?

delay : Delay in millisecond to execute function. invokeApply : If true then invoke fn within the $apply block. Pass : Additional parameters to the executed function. We will create simple angularjs example to understand $timeout service using a method.We will create a method that will show ‘Hello’ message into console and execute after 2 sec.


2 Answers

ngInclude provides an onload attribute which will evaluate an expression when it is loaded; does that give you what you need?

<div vector-draw-directive class="thirdlevel"
  ng-repeat="firstlevel in secondlevel.children"
  ng-include="'templateLevel2.html'" onload="loaded()">
</div>

Very basic example: http://jsfiddle.net/BinaryMuse/KRbdL/121/

like image 136
Michelle Tilley Avatar answered Sep 24 '22 20:09

Michelle Tilley


You can kinda use the window.requestAnimationFrame callback to figure out when angular is done manipulating the DOM, like so:

var fn = function () {
    var elm = document.getElementById('elementID');

    if(elm == null) {
        window.requestAnimationFrame(fn);
    } else {
        doSomething();
    }
};
fn();

It's a hack though, so use at your own risk

like image 32
Rasive Avatar answered Sep 23 '22 20:09

Rasive