AngularJS: Running a directive after data has been fetched

In one of my AngularJS projects, I am using the angular-split-pane directive which is basically wrapping the split-pane JQuery plugin. This directive finds out how to split the panes and position the slider by reading the height and width attributes of the HTML tag.

I needed to add a functionality to my application so that the position of the slider is written to some session file on the server and reused next time the application is started to reposition the sliders at the same position, basically setting the height of the lower pane in percentage.

The previous position is fetched using $http. The problem is that it runs asynchronously and by the time the results are there, the directive has already been processed and changing the height tag has no effect anymore.

You can define the order in which directives are run by setting the priority property. But I needed a way to have the directive processed after the results from the server were available, not after or before another directive is processed.

After searching for a solution for quite some time, I finally find a way of implementing it late at night. This is actually pretty simple but for some reason it took me forever to think about such a solution.

When I fetch the data from the server I set some variable in my scope e.g.:

$http.get("../api/Config/").success(function(data) {
	sessionModel.ui = data;
});

Since I only want to execute the directive once the data is fetched, this means I want to have it executed once sessionModel.ui has a value. So all I need to do is add an ng-if attribute to my tag. Since the variable is initially not set, AngularJS will remove the element from the DOM and once the value is set, it will recreate it having the directive executed. So my tag would now look like this:

<split-pane ng-if="sessionModel.ui">

Of course the small disadvantage of this solution is that my UI is first shortly rendered without the split pane and when the data has been fetched, the split-pane is also rendered. In order not to have a partial rendering of the UI, you could of course move the ng-if attribute higher in your HTML code so that the whole UI is only rendered once the data from the server is available.

If your directive is not replacing the DOM element but just manipulating them, another solution would be to have the logic run asynchronously using $timeout and repeat until the data from the server is available. Or having it applied once the data is available by using $watch.

Leave a Reply

Your email address will not be published. Required fields are marked *