core
core

Reputation: 33079

Accessing yet-to-be-compiled directive's DOM elements from controller

I've got a controller that executes before Angular compiles a directive. The controller needs to manipulate a DOM element that only exists after the directive has been compiled. How can I select that DOM element, to manipulate it, if it's not in the DOM yet?

A contrived example to illustrate this follows. Let's say I have the following markup:

<div ng-controller="CustomerCtrl">
    <div customer-list></div>
</div>

customerList is a directive that is transformed into:

<select class="customer-list">
    <option value="JohnDoe">John Doe</option>
    <option value="JaneDoe">Jane Doe</option>
</select>

CustomerCtrl looks like:

.controller('CustomerCtrl', function() {
    var customerList = angular.element('[customer-list]'),
        firstCustomer = customerList.children('option:first');

    // firstCustomer is length === 0 at this point, so
    // this code does not work
    firstCustomer.prop('selected', 'selected');
});

My solution was to do this:

.controller('CustomerCtrl', function($timeout) {
    var customerList = angular.element('[customer-list]');

    // this works
    $timeout(function() {
        customerList.children('option:first').prop('selected', 'selected');
    });
});

What I'm wondering is, is this the appropriate way to do this--using a $timeout()? Is there a best practice about this?

Upvotes: 0

Views: 18

Answers (1)

Sid
Sid

Reputation: 7631

You should be using the directive's link function to do this sort of manipulation. Then you won't have ot use timeout. Such DOM manipulation really belongs to the directive rather than the controller. The controller is simply the holder of scope and really shouldn't have much much of application/ui logic in it. The link is guaranteed to be called after your directive is compiled so you should be good if you use link.

Upvotes: 1

Related Questions