Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is binding value not available in controller immediately in angular

Tags:

angularjs

I'm trying to bind some values in an angular 1.6 component that should be available to the controller code.

I must be misunderstanding it, but the variables aren't available when the controller runs. The only way I've managed it is by putting a $timeout in to push the code into the next digest cycle.

What am I doing wrong here?

The relevant section is here:

var SelectorCtrl = ['$scope', '$http', '$timeout',
  function ($scope, $http, $timeout) {
    var self = this;
    alert("1: " + self.hierarchyId);

    // I'm not 100% sure why this has to be in the next digest cycle
    $timeout(function(){
      $scope.categories = self.categories;
      alert("2: " + self.hierarchyId);

    });
}

app.component('categorySelector', {
  templateUrl: 'categorySelector.html',
  controller: SelectorCtrl,
  bindings: {
    hierarchyId: "@",
    disabled: "=",
    categories: "=",
    onSelectionChanged: "&"
  }
});

See plunker: https://plnkr.co/edit/8rtDuCawdHaiXzQU5VBR

like image 382
Richard G Avatar asked Jan 20 '17 03:01

Richard G


People also ask

What is 2 way binding in Angular?

Angular's two-way binding syntax is a combination of square brackets and parentheses, [()] . The [()] syntax combines the brackets of property binding, [] , with the parentheses of event binding, () , as follows.

How data binding happens in AngularJS?

Data binding in AngularJS is the synchronization between the model and the view. When data in the model changes, the view reflects the change, and when data in the view changes, the model is updated as well.

What is controlleras AngularJS?

The controller in AngularJS is a JavaScript function that maintains the application data and behavior using $scope object. You can attach properties and methods to the $scope object inside a controller function, which in turn will add/update the data and attach behaviours to HTML elements.

Is AngularJS supports two way binding?

AngularJS creates a two way data-binding between the select element and the $ctrl.


1 Answers

This is because of $compileProvider.preAssignBindingsEnabled(flag) introduced in Angular 1.6, you can configure it on config cycle on $compileProvider

If disabled (false), the compiler calls the constructor first before assigning bindings.

The default value is true in Angular 1.5.x but will switch to false in Angular 1.6.x.

You will get all bindings inside $onInit lifecycle event of Angular component, where all the bindings would be available(if binding passed synchronously).

self.$onInit = function() {
  $scope.categories = self.categories;
  alert("2: " + self.hierarchyId);
};

Note: It's bad practice to mix $scope with this. Rather avoid using $scope to make your code Angular 2 migration proof.


If you want binding to be available when controller function instantiate then you could set $compileProvider.preAssignBindingsEnabled(true). Which will make self.categories(bindings) value.

app.config(function($compileProvider){
   $compileProvider.preAssignBindingsEnabled(true)
});

Similar answer


Angular 1.7.x update

As of Angular 1.7.x, the $compileProvider.preAssignBindingsEnabled(flag) is gone, and it is no longer possible to assign bindings before the constructor.

To work around this, you need to define a link function in your directive definition. You can make this function call a method on your controller like this:

app.directive("directive", function() {
  return {
    controller: DirectiveController, // bind controller any way you want
    controllerAs: "ctrl",
    bindToController: true,
    link: function(scope) {
      scope.ctrl.init(); // this will call an init() function on your controller
    }
  }
});
like image 87
Pankaj Parkar Avatar answered Oct 08 '22 18:10

Pankaj Parkar