Reputation: 5683
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
Upvotes: 6
Views: 1945
Reputation: 136154
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
withthis
. 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)
});
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
}
}
});
Upvotes: 9