fix(ivy): @Component should support entry components from another module (#29566)
PR Close #29566
This commit is contained in:
parent
acfcf90528
commit
d47de60944
|
@ -14,6 +14,7 @@ import {Type} from '../../interface/type';
|
||||||
import {registerNgModuleType} from '../../linker/ng_module_factory_loader';
|
import {registerNgModuleType} from '../../linker/ng_module_factory_loader';
|
||||||
import {Component} from '../../metadata';
|
import {Component} from '../../metadata';
|
||||||
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
|
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
|
||||||
|
import {flatten} from '../../util/array_utils';
|
||||||
import {assertDefined} from '../../util/assert';
|
import {assertDefined} from '../../util/assert';
|
||||||
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
|
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
|
||||||
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
|
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
|
||||||
|
@ -158,6 +159,7 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
|
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
|
||||||
const imports = maybeUnwrapFn(ngModuleDef.imports);
|
const imports = maybeUnwrapFn(ngModuleDef.imports);
|
||||||
|
flatten(imports, unwrapModuleWithProvidersImports).forEach(verifySemanticsOfNgModuleDef);
|
||||||
const exports = maybeUnwrapFn(ngModuleDef.exports);
|
const exports = maybeUnwrapFn(ngModuleDef.exports);
|
||||||
declarations.forEach(verifyDeclarationsHaveDefinitions);
|
declarations.forEach(verifyDeclarationsHaveDefinitions);
|
||||||
const combinedDeclarations: Type<any>[] = [
|
const combinedDeclarations: Type<any>[] = [
|
||||||
|
@ -464,18 +466,6 @@ export function transitiveScopesFor<T>(
|
||||||
return scopes;
|
return scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flatten<T>(values: any[], mapFn?: (value: T) => any): Type<T>[] {
|
|
||||||
const out: Type<T>[] = [];
|
|
||||||
values.forEach(value => {
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
out.push(...flatten<T>(value, mapFn));
|
|
||||||
} else {
|
|
||||||
out.push(mapFn ? mapFn(value) : value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): Type<any> {
|
function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): Type<any> {
|
||||||
if (isModuleWithProviders(value)) {
|
if (isModuleWithProviders(value)) {
|
||||||
return value.ngModule;
|
return value.ngModule;
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function addAllToArray(items: any[], arr: any[]) {
|
||||||
/**
|
/**
|
||||||
* Flattens an array in non-recursive way. Input arrays are not modified.
|
* Flattens an array in non-recursive way. Input arrays are not modified.
|
||||||
*/
|
*/
|
||||||
export function flatten(list: any[]): any[] {
|
export function flatten(list: any[], mapFn?: (value: any) => any): any[] {
|
||||||
const result: any[] = [];
|
const result: any[] = [];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (i < list.length) {
|
while (i < list.length) {
|
||||||
|
@ -34,7 +34,7 @@ export function flatten(list: any[]): any[] {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.push(item);
|
result.push(mapFn ? mapFn(item) : item);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, InjectionToken} from '@angular/core';
|
import {Component, ComponentFactoryResolver, ComponentRef, InjectionToken, NgModule, Type, ViewChild, ViewContainerRef} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
|
|
||||||
|
|
||||||
describe('component', () => {
|
describe('component', () => {
|
||||||
|
@ -49,4 +50,42 @@ describe('component', () => {
|
||||||
expect(destroyCalls).toBe(1, 'Expected `ngOnDestroy` to only be called once.');
|
expect(destroyCalls).toBe(1, 'Expected `ngOnDestroy` to only be called once.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support entry components from another module', () => {
|
||||||
|
@Component({selector: 'other-component', template: `bar`})
|
||||||
|
class OtherComponent {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [OtherComponent],
|
||||||
|
exports: [OtherComponent],
|
||||||
|
entryComponents: [OtherComponent]
|
||||||
|
})
|
||||||
|
class OtherModule {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'test_component',
|
||||||
|
template: `foo|<ng-template #vc></ng-template>`,
|
||||||
|
entryComponents: [OtherComponent]
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
@ViewChild('vc', {read: ViewContainerRef}) vcref !: ViewContainerRef;
|
||||||
|
|
||||||
|
constructor(private _cfr: ComponentFactoryResolver) {}
|
||||||
|
|
||||||
|
createComponentView<T>(cmptType: Type<T>): ComponentRef<T> {
|
||||||
|
const cf = this._cfr.resolveComponentFactory(cmptType);
|
||||||
|
return this.vcref.createComponent(cf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [TestComponent], imports: [OtherModule]});
|
||||||
|
const fixture = TestBed.createComponent(TestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.componentInstance.createComponentView(OtherComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.nativeElement).toHaveText('foo|bar');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue