fix(UpgradeNg1ComponentAdapter): make bindings available on $scope in controller & link function (#8645)

Delays NG1 Directive controller instatiation where possible and pre-link function always
to the ngOnInit() lifecycle hook. This way bindings are always available on $scope in both
the controller and the link function.
This commit is contained in:
Hannah Howard
2016-05-17 14:53:59 -07:00
committed by Miško Hevery
parent 15ae710d22
commit 6cdc53c497
2 changed files with 117 additions and 18 deletions

View File

@ -186,33 +186,22 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
checkLastValues: any[] = [];
componentScope: angular.IScope;
element: Element;
$element: any = null;
constructor(private linkFn: angular.ILinkFn, scope: angular.IScope,
private directive: angular.IDirective, elementRef: ElementRef,
$controller: angular.IControllerService, private inputs: string[],
private $controller: angular.IControllerService, private inputs: string[],
private outputs: string[], private propOuts: string[],
private checkProperties: string[], private propertyMap: {[key: string]: string}) {
this.element = elementRef.nativeElement;
this.componentScope = scope.$new(!!directive.scope);
var $element = angular.element(this.element);
this.$element = angular.element(this.element);
var controllerType = directive.controller;
var controller: any = null;
if (controllerType) {
var locals = {$scope: this.componentScope, $element: $element};
controller = $controller(controllerType, locals, null, directive.controllerAs);
$element.data(controllerKey(directive.name), controller);
if (directive.bindToController && controllerType) {
this.destinationObj = this.buildController(controllerType);
} else {
this.destinationObj = this.componentScope;
}
var link = directive.link;
if (typeof link == 'object') link = (<angular.IDirectivePrePost>link).pre;
if (link) {
var attrs: angular.IAttributes = NOT_SUPPORTED;
var transcludeFn: angular.ITranscludeFunction = NOT_SUPPORTED;
var linkController = this.resolveRequired($element, directive.require);
(<angular.IDirectiveLinkFn>directive.link)(this.componentScope, $element, attrs,
linkController, transcludeFn);
}
this.destinationObj =
directive.bindToController && controller ? controller : this.componentScope;
for (var i = 0; i < inputs.length; i++) {
this[inputs[i]] = null;
@ -225,9 +214,24 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
this[propOuts[k]] = new EventEmitter();
this.checkLastValues.push(INITIAL_VALUE);
}
}
ngOnInit() {
if (!this.directive.bindToController && this.directive.controller) {
this.buildController(this.directive.controller)
}
var link = this.directive.link;
if (typeof link == 'object') link = (<angular.IDirectivePrePost>link).pre;
if (link) {
var attrs: angular.IAttributes = NOT_SUPPORTED;
var transcludeFn: angular.ITranscludeFunction = NOT_SUPPORTED;
var linkController = this.resolveRequired(this.$element, this.directive.require);
(<angular.IDirectiveLinkFn>this.directive.link)(this.componentScope, this.$element, attrs,
linkController, transcludeFn);
}
var childNodes: Node[] = [];
var childNode;
while (childNode = this.element.firstChild) {
@ -277,6 +281,13 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
this.destinationObj[this.propertyMap[name]] = value;
}
private buildController(controllerType) {
var locals = { $scope: this.componentScope, $element: this.$element };
var controller:any = this.$controller(controllerType, locals, null, this.directive.controllerAs);
this.$element.data(controllerKey(this.directive.name), controller);
return controller;
}
private resolveRequired($element: angular.IAugmentedJQuery, require: string | string[]): any {
if (!require) {
return undefined;