Skip to content

Commit

Permalink
fix(upgrade): call ng1 lifecycle hooks (#12875)
Browse files Browse the repository at this point in the history
  • Loading branch information
bradyisom authored and chuckjaz committed Nov 18, 2016
1 parent 07a986d commit 1ef4696
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 9 deletions.
29 changes: 20 additions & 9 deletions modules/@angular/upgrade/src/upgrade_ng1_adapter.ts
Expand Up @@ -49,7 +49,8 @@ export class UpgradeNg1ComponentAdapterBuilder {
],
ngOnInit: function() { /* needs to be here for ng2 to properly detect it */ },
ngOnChanges: function() { /* needs to be here for ng2 to properly detect it */ },
ngDoCheck: function() { /* needs to be here for ng2 to properly detect it */ }
ngDoCheck: function() { /* needs to be here for ng2 to properly detect it */ },
ngOnDestroy: function() { /* needs to be here for ng2 to properly detect it */ },
});
}

Expand Down Expand Up @@ -262,16 +263,18 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
}

ngOnChanges(changes: SimpleChanges) {
for (const name in changes) {
if ((<Object>changes).hasOwnProperty(name)) {
const change: SimpleChange = changes[name];
this.setComponentProperty(name, change.currentValue);
}
const ng1Changes: any = {};
Object.keys(changes).forEach(name => {
const change: SimpleChange = changes[name];
this.setComponentProperty(name, change.currentValue);
ng1Changes[this.propertyMap[name]] = change;
});
if (this.destinationObj.$onChanges) {
this.destinationObj.$onChanges(ng1Changes);
}
}

ngDoCheck(): number {
const count = 0;
ngDoCheck() {
const destinationObj = this.destinationObj;
const lastValues = this.checkLastValues;
const checkProperties = this.checkProperties;
Expand All @@ -287,7 +290,15 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
}
}
}
return count;
if (this.destinationObj.$doCheck && this.directive.controller) {
this.destinationObj.$doCheck();
}
}

ngOnDestroy() {
if (this.destinationObj.$onDestroy && this.directive.controller) {
this.destinationObj.$onDestroy();
}
}

setComponentProperty(name: string, value: any) {
Expand Down
121 changes: 121 additions & 0 deletions modules/@angular/upgrade/test/upgrade_spec.ts
Expand Up @@ -922,6 +922,127 @@ export function main() {
});
}));

it('should call $doCheck of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const valueToFind = '$doCheck';

let spy = jasmine.createSpy('doCheck');

const ng1 = {
bindings: {},
template: '{{$ctrl.value}}',
controller: Class({
constructor: function() {},
$doCheck: function() {
this.value = valueToFind;
spy();
}
})
};
ng1Module.component('ng1', ng1);

const Ng2 = Component({selector: 'ng2', template: '<ng1></ng1>'}).Class({
constructor: function() {}
});

const Ng2Module = NgModule({
declarations: [adapter.upgradeNg1Component('ng1'), Ng2],
imports: [BrowserModule],
schemas: [NO_ERRORS_SCHEMA],
}).Class({constructor: function() {}});

ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));

const element = html(`<div><ng2></ng2></div>`);
adapter.bootstrap(element, ['ng1']).ready((ref) => {
expect(multiTrim(document.body.textContent)).toEqual(valueToFind);
expect(spy).toHaveBeenCalled();
let count = spy.calls.count();
setTimeout(() => {
expect(spy.calls.count()).toBeGreaterThan(count);
ref.dispose();
}, 100);
});
}));

it('should call $onChanges of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
const valueToFind = '$onChanges init';
const valueToChange = '$onChanges changed';

const ng1 = {
bindings: {val: '<'},
template: '{{$ctrl.value}}',
controller: Class({
constructor: function() {},
$onChanges: function(changes: any) { this.value = changes.val.currentValue; }
})
};
ng1Module.component('ng1', ng1);

const Ng2 = Component({selector: 'ng2', template: '<ng1 [val]="val"></ng1>'}).Class({
constructor: function() { this.val = valueToFind; },
ngOnInit: function() { setTimeout(() => { this.val = valueToChange; }, 100); }
});

const Ng2Module = NgModule({
declarations: [adapter.upgradeNg1Component('ng1'), Ng2],
imports: [BrowserModule],
schemas: [NO_ERRORS_SCHEMA],
}).Class({constructor: function() {}});

ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));

const element = html(`<div><ng2></ng2></div>`);
adapter.bootstrap(element, ['ng1']).ready((ref) => {
expect(multiTrim(document.body.textContent)).toEqual(valueToFind);
setTimeout(() => {
expect(multiTrim(document.body.textContent)).toEqual(valueToChange);
ref.dispose();
}, 200);
});
}));

it('should call $onDestroy of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);

let spy = jasmine.createSpy('$onDestroy');

const ng1 = {
bindings: {},
template: '<div>ng1</div>',
controller: function($rootScope: any) { this.$onDestroy = function() { spy(); }; }
};
ng1Module.component('ng1', ng1);

const Ng2 = Component({selector: 'ng2', template: '<ng1></ng1>'}).Class({
constructor: function() {}
});

const Ng2Module = NgModule({
declarations: [adapter.upgradeNg1Component('ng1'), Ng2],
imports: [BrowserModule],
schemas: [NO_ERRORS_SCHEMA],
}).Class({constructor: function() {}});

ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));

const element = html(`<div ng-if="!destroy"><ng2></ng2></div>`);
adapter.bootstrap(element, ['ng1']).ready((ref) => {
(<any>ref.ng1RootScope).destroy = false;
setTimeout(() => {
(<any>ref.ng1RootScope).destroy = true;
setTimeout(() => {
expect(spy).toHaveBeenCalled();
ref.dispose();
}, 100);
}, 100);
});
}));

it('should bind input properties (<) of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
Expand Down

0 comments on commit 1ef4696

Please sign in to comment.