fix(upgrade): make upgradeAdapter upgrade angular 1 components correctly
With this fix, the $onInit function of an upgraded angular 1 component is called and input bindings (<) are created. Closes #7951
This commit is contained in:
parent
5e2bc5c593
commit
247964af62
|
@ -1,6 +1,7 @@
|
||||||
export interface IModule {
|
export interface IModule {
|
||||||
config(fn: any): IModule;
|
config(fn: any): IModule;
|
||||||
directive(selector: string, factory: any): IModule;
|
directive(selector: string, factory: any): IModule;
|
||||||
|
component(selector: string, component: IComponent): IModule;
|
||||||
controller(name: string, type: any): IModule;
|
controller(name: string, type: any): IModule;
|
||||||
factory(key: string, factoryFn: any): IModule;
|
factory(key: string, factoryFn: any): IModule;
|
||||||
value(key: string, value: any): IModule;
|
value(key: string, value: any): IModule;
|
||||||
|
@ -59,6 +60,15 @@ export interface IDirectiveLinkFn {
|
||||||
(scope: IScope, instanceElement: IAugmentedJQuery, instanceAttributes: IAttributes,
|
(scope: IScope, instanceElement: IAugmentedJQuery, instanceAttributes: IAttributes,
|
||||||
controller: any, transclude: ITranscludeFunction): void;
|
controller: any, transclude: ITranscludeFunction): void;
|
||||||
}
|
}
|
||||||
|
export interface IComponent {
|
||||||
|
bindings?: Object;
|
||||||
|
controller?: any;
|
||||||
|
controllerAs?: string;
|
||||||
|
require?: any;
|
||||||
|
template?: any;
|
||||||
|
templateUrl?: any;
|
||||||
|
transclude?: any;
|
||||||
|
}
|
||||||
export interface IAttributes { $observe(attr: string, fn: (v: string) => void): void; }
|
export interface IAttributes { $observe(attr: string, fn: (v: string) => void): void; }
|
||||||
export interface ITranscludeFunction {
|
export interface ITranscludeFunction {
|
||||||
// If the scope is provided, then the cloneAttachFn must be as well.
|
// If the scope is provided, then the cloneAttachFn must be as well.
|
||||||
|
|
|
@ -53,6 +53,7 @@ export class UpgradeNg1ComponentAdapterBuilder {
|
||||||
self.outputs, self.propertyOutputs, self.checkProperties, self.propertyMap);
|
self.outputs, self.propertyOutputs, self.checkProperties, self.propertyMap);
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
ngOnInit: function() { /* needs to be here for ng2 to properly detect it */ },
|
||||||
ngOnChanges: 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 */ }
|
||||||
});
|
});
|
||||||
|
@ -106,6 +107,8 @@ export class UpgradeNg1ComponentAdapterBuilder {
|
||||||
this.propertyMap[outputName] = localName;
|
this.propertyMap[outputName] = localName;
|
||||||
// don't break; let it fall through to '@'
|
// don't break; let it fall through to '@'
|
||||||
case '@':
|
case '@':
|
||||||
|
// handle the '<' binding of angular 1.5 components
|
||||||
|
case '<':
|
||||||
this.inputs.push(inputName);
|
this.inputs.push(inputName);
|
||||||
this.inputsRename.push(inputNameRename);
|
this.inputsRename.push(inputNameRename);
|
||||||
this.propertyMap[inputName] = localName;
|
this.propertyMap[inputName] = localName;
|
||||||
|
@ -231,6 +234,13 @@ class UpgradeNg1ComponentAdapter implements OnChanges, DoCheck {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.destinationObj.$onInit) {
|
||||||
|
this.destinationObj.$onInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: {[name: string]: SimpleChange}) {
|
ngOnChanges(changes: {[name: string]: SimpleChange}) {
|
||||||
for (var name in changes) {
|
for (var name in changes) {
|
||||||
if ((<Object>changes).hasOwnProperty(name)) {
|
if ((<Object>changes).hasOwnProperty(name)) {
|
||||||
|
|
|
@ -561,6 +561,65 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should call $onInit of components', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var adapter = new UpgradeAdapter();
|
||||||
|
var ng1Module = angular.module('ng1', []);
|
||||||
|
var valueToFind = '$onInit';
|
||||||
|
|
||||||
|
var ng1 = {
|
||||||
|
bindings: {},
|
||||||
|
template: '{{$ctrl.value}}',
|
||||||
|
controller: Class(
|
||||||
|
{constructor: function() {}, $onInit: function() { this.value = valueToFind; }})
|
||||||
|
};
|
||||||
|
ng1Module.component('ng1', ng1);
|
||||||
|
|
||||||
|
var Ng2 = Component({
|
||||||
|
selector: 'ng2',
|
||||||
|
template: '<ng1></ng1>',
|
||||||
|
directives: [adapter.upgradeNg1Component('ng1')]
|
||||||
|
}).Class({constructor: function() {}});
|
||||||
|
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
|
||||||
|
|
||||||
|
var element = html(`<div><ng2></ng2></div>`);
|
||||||
|
adapter.bootstrap(element, ['ng1'])
|
||||||
|
.ready((ref) => {
|
||||||
|
expect(multiTrim(document.body.textContent)).toEqual(valueToFind);
|
||||||
|
ref.dispose();
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should bind input properties (<) of components', inject([AsyncTestCompleter], (async) => {
|
||||||
|
var adapter = new UpgradeAdapter();
|
||||||
|
var ng1Module = angular.module('ng1', []);
|
||||||
|
|
||||||
|
var ng1 = {
|
||||||
|
bindings: {personProfile: '<'},
|
||||||
|
template: 'Hello {{$ctrl.personProfile.firstName}} {{$ctrl.personProfile.lastName}}',
|
||||||
|
controller: Class({constructor: function() {}})
|
||||||
|
};
|
||||||
|
ng1Module.component('ng1', ng1);
|
||||||
|
|
||||||
|
var Ng2 =
|
||||||
|
Component({
|
||||||
|
selector: 'ng2',
|
||||||
|
template: '<ng1 [personProfile]="goku"></ng1>',
|
||||||
|
directives: [adapter.upgradeNg1Component('ng1')]
|
||||||
|
})
|
||||||
|
.Class({
|
||||||
|
constructor: function() { this.goku = {firstName: 'GOKU', lastName: 'SAN'}; }
|
||||||
|
});
|
||||||
|
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
|
||||||
|
|
||||||
|
var element = html(`<div><ng2></ng2></div>`);
|
||||||
|
adapter.bootstrap(element, ['ng1'])
|
||||||
|
.ready((ref) => {
|
||||||
|
expect(multiTrim(document.body.textContent)).toEqual(`Hello GOKU SAN`);
|
||||||
|
ref.dispose();
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('injection', () => {
|
describe('injection', () => {
|
||||||
|
|
Loading…
Reference in New Issue