How to run Controller first before Angularjs directive?

Could help me in giving an example or documentation of how to render the entire controller first before a custom directive is executed.

What I have in the controller is a value: $scope.total = 200;

In the HTML I have the following

<div val-Custom><ul><li data-value="{{total}}"></li></ul></div>

Now I want to catch that value in my ejem directive:

ctrlsaldosyconsumos.directive('valCustom', function() {
return function(scope, element, attrs) {
    //aqui hago otras cosas me interesa mas 
    attrs.$observe('valCustom', function() {
         element.find('li').animate({ width: element.attr("data-value") + '%' }, 350);
    });
}
})

Now that data-value in the directive comes out to me undefined and if I put it, for example

<li data-value="200"></li> 

This does execute correctly. I think the directive is running first without having loaded the controller value ($scope.total).

Any suggestions or help I will thank you, I am starting on this from AngularJS (Angular 1) and more in directives. Thank you.

 5
Author: ivanao, 2016-10-04

3 answers

Short answer:

The controller always runs first before the{[11 directive]}

Long answer:

First of all remember that ng-controller is a directive as well. The order of execution of directives is as follows

compile padre
compile hijo
controller padre  =>  ng-controller
pre-link padre
controller hijo   =>  tu directiva
pre-link hijo
post-link hijo
post-link padre

You can check it in the following snippet

angular.module('app', [])
  .directive('padre', function() {
    return {
      restrict: 'E',
      compile: function() {
        console.log('Compile padre');
        return {
          pre: function() {
            console.log('Pre padre');
          },
          post: function() {
            console.log('Post padre');
          }
        };
      },
      controller: function() {
        console.log('Controller padre');
      }
    };
  })
  .directive('hijo', function() {
    return {
      restrict: 'E',
      compile: function() {
        console.log('Compile hijo');
        return {
          pre: function() {
            console.log('Pre hijo');
          },
          post: function() {
            console.log('Post hijo');
          }
        };
      },
      controller: function() {
        console.log('Controller hijo');
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <padre>
    <hijo></hijo>
  </padre>
</div>

Which means that if your directive is in the DOM inside your controller it will never execute first of all.

If your code depends on Ajax calls, it doesn't matter in the order you execute it, your directive is likely to reach Phase post-link and the results haven't arrived yet via ajax.

The solution could be to use ng-if to signal when the directive can be rendered.

angular.module('app', [])
  .controller('UtilCtrl', function($scope, $timeout) {
    $scope.muestraHijo = false;
    $timeout(function() {
      $scope.muestraHijo = true;
    }, 1000)
  })
  .directive('padre', function() {
    return {
      restrict: 'E',
      compile: function() {
        console.log('Compile padre');
        return {
          pre: function() {
            console.log('Pre padre');
          },
          post: function() {
            console.log('Post padre');
          }
        };
      },
      controller: function() {
        console.log('Controller padre');
      }
    };
  })
  .directive('hijo', function() {
    return {
      restrict: 'E',
      compile: function() {
        console.log('Compile hijo');
        return {
          pre: function() {
            console.log('Pre hijo');
          },
          post: function() {
            console.log('Post hijo');
          }
        };
      },
      controller: function() {
        console.log('Controller hijo');
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="UtilCtrl">
  <padre>
    <div ng-if="muestraHijo">
      <hijo></hijo>
    </div>
  </padre>
</div>

Lee https://github.com/angular/angular.js/wiki/Understanding-Directives

If you need to wait for $scope data has finished loading try using ng-if to delay processing of a DOM block.

 2
Author: devconcept, 2016-10-12 16:10:13

Similar problem, I solved it by considering $watch Inside My directive controller, in this case it was a collection type attribute:

$scope.$watchCollection("datos", function (newValue, oldValue) {            
    if (newValue === oldValue) {
        return;
    }
    if ($scope.datos != undefined)
        loadGraphEChart($scope.labels, $scope.datos, $scope.titulo, $scope.idgraph);
});

With the above, I managed to get the loadGraphEChart to run once

$scope.datos != undefined

Note: the data value was not assigned given some user event, but was fed as a policy attribute given the response to an http request

<div echart-graph ng-model="edades"
                                                     idgraph="Edades"
                                                     stilo="height:350px;width:98%;"
                                                     titulo="Edades"
                                                     labels="edades.labels"
                                                     datos="edades.datos"></div>
 0
Author: user47161, 2017-06-10 23:44:06

Maybe this can guide you, I solve it like this:

<div val-Custom algo="$scope.algo">
    <ul>
        <li data-value="{{total}}"></li>
    </ul>
</div>

In your directive indicate the following:

ctrlsaldosyconsumos.directive('valCustom', function() {
    return {
      restrict: 'A',
      scope: {
        algo: '=algo'
      },
      link: function(scope, elem, attr){
        console.log("llamando al scope.algo deberias tener disponible tus datos")
        attrs.$observe('valCustom', function() {
            element.find('li').animate({ width: element.attr("data-value") + '%' }, 350);
        });
      }
    }
})

This might help you understand how it works:

Documentary AngularJS (Angular 1)

Navigate to the part that says: Isolating the Scope of a Directive

Greetings, I hope to help or guide you.

 0
Author: Mauricio Zarallo, 2019-09-02 12:47:37