sylvain1264
sylvain1264

Reputation: 855

How to access a dom element in a directive from page controller

I try to access an element that is in a directive, but my controller doesn't find it, how to do it ? In the example below, variable canvas in controller MyCtrl is null.

Edit: Concretely my directive is a custom collapse, so the content into it can be various. For example, I have a view which display informations that are in those collapses made by my directive, and user can edit it. By the way, the business logic is in the view controller, it handles data load and send user modification. Code below edited to be more accurate.

html:

<div ng-controller="MyCtrl">
    <collapsible-div title="Open Me">
        <canvas id="myCanvas"></span>
    </collapsible-div>
</div>

controller:

myApp.controller("MyCtrl",['$scope', function($scope) {

    var canvas  = document.getElementById('myCanvas');
    /* Some code do draw image in my canvas... */

}]);

directive:

myApp.directive('collapsibleDiv', function(){
    return {
        restrict: 'E',
        transclude: true,
        replace: true,
        scope: {
            title: '@'
        },
        controller: function ($scope, $element) {
            /* Some code to make my collapsible div how I want... */
            /* This has nothing to deal with content, this directive can store any kind of content */
        },
        templateUrl: 'collapsible.html'
    };
});

Final solution: A controller shouldn't access directive dom, I may use a more modular approach using a new directive to handle my canvas, my html looks like this now, and my controller is empty:

<collapsible-div title="Open Me">
    <my-canvas></my-canvas>
</collapsible-div>

Upvotes: 3

Views: 5180

Answers (2)

user3111116
user3111116

Reputation: 1

You can use link in the directive, then you will have access to the element declarated. Example:

myApp.directive('directive', function(){
    return {
        restrict: 'E',
        transclude: true,
        replace: true,
        template: '<div ng-transclude></div>',
        link: function(scope, element, attrs){
              //Here you have control over element
              console.log(element); 
              //for example, you can create events on the element
              element.bind('click', function(){
                     //put your code here
              });

        }
    };
});

Upvotes: 0

avcajaraville
avcajaraville

Reputation: 9084

I think you are having problems understanding the differences between a directive and a controller. I suggest you to go deeper on those concepts.

On your specific problem, as you are using a directive, and also because you should manage all DOM operations on a directive, the place to put it will be the link function of your directive.

In this case, something like this:

myApp.directive('directive', function(){
    var directive = {
        restrict: 'E',
        transclude: true,
        replace: true,
        template: '<div ng-transclude></div>'
        link : directiveLinkFunction
    };

    function directiveLinkFunction( scope, element, attrs ) {

      // element -> the DOM element that hold the directive.
      // for different selection, use the jQuery lite API

    }

    return directive;
});

You then need to use some other strategies to share data between controller and directive, but thats is a whole different topic.

Main point -> do all DOM manipulations on a directive.

Upvotes: 1

Related Questions