2

I'm trying to come up with some code which allows me to run a function in the controller but only once the whole dom is setup and ready (including the directives link function run etc.).

I'm currently communicating between ctrl/service and the directive via $rootScope broadcasts. The first broadcast at the time of the controller loading is not being picked up by the directive. The reason is of course that the controller loads before the directive link function runs. I've read a few similar questions on SO where people recommended on using $timeout for these calls. This unfortunately doesn't always work and I don't want to clutter my ctrl/services with lots of $timeout calls. Therefore I'm looking for another solution to my problem.

Communication pattern is as follows:

1.) Controller tells Service to prepare some data (via function call in service)

2.) Service tells directive to display data (via broadcast)

3.) Directive displays data ...or not in my case :(

EDIT:

As timing is essential in my app, I'm basically looking for a way to initiate a function in the controller as soon as all angular components have finished loading. That function in the controller will display content by assigning a value to a scope variable. At the same time it will start taking the time. I can of course only start doing that once the directives are loaded, otherwise the tmining is wrong or the directive is not yet ready to display content etc.

I've read through a blog post by Ben Nadel, which basically shows how directives are loaded. I was hoping to setup an outer directive which loads last so I can trigger the finished loading from there. Unfortunately that doesn't work as soon as any of the inner directives use a templateUrl. http://www.bennadel.com/blog/2603-directive-controller-and-link-timing-in-angularjs.htm

1 Answer 1

4

Using $timeout would be terrible. Don't do that. You can't define how long a server call is going to take.

I would recommend using this pattern:

  • Have the controller use a service to load some data, and have the promise in the controller assign the return data to a scope variable.
  • Pass that scope variable into your directive.
  • Setup a watch in the directive link function, when it loads it will go from undefined to desired value. Done!

// in your controller

YourService.all().then(function(data) {
  $scope.data = data;
});

// in your view

<some-directive your-data="data"></some-directive>

// in your directive

angular.module('blah.directives').directive('someDirective', function() {
    return {
      scope: {
        yourData: '='
      },
      link: function(scope, element, attrs) {

        var watcher = scope.$watch('yourData', function() {
          if(scope.yourData === undefined) return;

          // at this point your data will be loaded, do work

          // optionally kill watcher at this point if it's not going to update again
          watcher();
        });
      }
    }
  });
Sign up to request clarification or add additional context in comments.

3 Comments

I came up with something similar but I'll have to rephrase my question a bit. Timinig is crucial in my app which is why I need to be sure that everything is ready before I run the first function in my controller.
But I can use the watch approach instead of the broadcast as the directive at least picks up the call to display something. The only problem now being that the change of the value in the controller and the update in the directive are not happening at the same time (I mean at least right after each other)
Yeah because everything would be asynchronous, you need to be using the right techniques. I'd need to see more of your problem to help your further. At this point communicating between the service, controller, and directive could be archived with event dispatching, data binding, and probably other stuff.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.