1

I'm trying to figure out AngularJS directives. I've got the following JSFiddle with an example of something I'm trying to do. https://jsfiddle.net/7smor9o4/

As you can see in the example, I expect the vm.alsoId variable to be equal to vm.theId. In the template vm.theId displays the correct value but vm.alsoId does not.

What am I doing wrong? How could I accomplish my goal.

If it helps the final idea is to execute something as the following:

function directive(service) {
  var vm = this;
  vm.entity = null;

  init();

  function init() {
    service.getEntity(vm.theId).then(function (entity) {
      vm.entity = entity;
    });
  }
}
1
  • vm.theId is not initialized to any value by the time you are assigning it to vm.alsoId. This is demonstrated here: jsfiddle.net/84d6e0b4 Commented Jan 30, 2017 at 1:05

2 Answers 2

2

As you've noticed, the bindToController bindings are not immediately available in the controller's constructor function (unlike $scope, which are). What you're looking for is a feature introduced with Angular 1.5: Lifecycle Hooks, and specifically $onInit.

You had the right idea; simply replace your init function definition and invocation as follows:

vm.$onInit = function () {
    service.getEntity(vm.theId).then(function (entity) {
      vm.entity = entity;
    });
};

And here is your updated fiddle. (Alternatively, without this solution, you'd have needed a watch.)

Sign up to request clarification or add additional context in comments.

Comments

2

Angular recommends that you bind a controller "only when you want to expose an API to other directives. Otherwise use link."

Here's a working fiddle using the link function.

angular.module('app', [])
  .directive('directive', directive);

angular.element(function() {
  angular.bootstrap(document, ['app']);
});

function directive() {
  return {
    restrict: 'E',
    scope: {
      theId: '<'
    },
    template: `
        alsoId: <span ng-bind="alsoId"></span>
      theId: <span ng-bind="theId"></span>`,
    link: link
  };
}
function link(scope, element, attrs) {

  init();

  function init() {
    scope.alsoId = scope.theId;
  }
}

4 Comments

Angular doesn't recommend anything like that (it is a framework and doesn't have its own opinion after all). Where did this quote come from? It is obsolete point of view that was displaced with Angular 1.5. and bindToController object. It is a milestone to easier Angular 2 migration.
The quotes were my indication that I was quoting the angular docs directly (see Angular Docs). Search for "Best Practice: use controller when you want to expose an API to other directives. Otherwise use link." It is in bold and highlighted.
I disagree that it is an obsolete point of view and Angular 2 migration is not relevant to this issue.
It is very relevant because migration became the priority for framework changes in 1.5 and higher. The quote you've posted was in the manual since the beginning of times, long before the appearance of bindToController. Using oldschool style is a matter of taste, but please, don't suggest it as the right way to do things in the answer, because it is not. $scope and link are outdated in 2017.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.