feat(core): allow custom selector when bootstrapping components (#15668)

- fixes #7136

PR Close #15668
This commit is contained in:
Christoph Krautz 2017-03-31 16:37:20 +02:00 committed by Miško Hevery
parent cb384e8ed3
commit 900a88b15d
3 changed files with 42 additions and 7 deletions

View File

@ -358,10 +358,15 @@ export abstract class ApplicationRef {
* specified application component onto DOM elements identified by the [componentType]'s
* selector and kicks off automatic change detection to finish initializing the component.
*
* Optionally, a component can be mounted onto a DOM element that does not match the
* [componentType]'s selector.
*
* ### Example
* {@example core/ts/platform/platform.ts region='longform'}
*/
abstract bootstrap<C>(componentFactory: ComponentFactory<C>|Type<C>): ComponentRef<C>;
abstract bootstrap<C>(
componentFactory: ComponentFactory<C>|Type<C>,
rootSelectorOrNode?: string|any): ComponentRef<C>;
/**
* Invoke this method to explicitly process change detection and its side-effects.
@ -491,7 +496,8 @@ export class ApplicationRef_ extends ApplicationRef {
view.detachFromAppRef();
}
bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>): ComponentRef<C> {
bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any):
ComponentRef<C> {
if (!this._initStatus.done) {
throw new Error(
'Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.');
@ -509,7 +515,8 @@ export class ApplicationRef_ extends ApplicationRef {
const ngModule = componentFactory instanceof ComponentFactoryBoundToModule ?
null :
this._injector.get(NgModuleRef);
const compRef = componentFactory.create(Injector.NULL, [], componentFactory.selector, ngModule);
const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
compRef.onDestroy(() => { this._unloadComponent(compRef); });
const testability = compRef.injector.get(Testability, null);

View File

@ -30,11 +30,11 @@ export function main() {
beforeEach(() => { mockConsole = new MockConsole(); });
function createRootEl() {
function createRootEl(selector = 'bootstrap-app') {
const doc = TestBed.get(DOCUMENT);
const rootEl = <HTMLElement>getDOM().firstChild(
getDOM().content(getDOM().createTemplate(`<bootstrap-app></bootstrap-app>`)));
const oldRoots = getDOM().querySelectorAll(doc, 'bootstrap-app');
getDOM().content(getDOM().createTemplate(`<${selector}></${selector}>`)));
const oldRoots = getDOM().querySelectorAll(doc, selector);
for (let i = 0; i < oldRoots.length; i++) {
getDOM().remove(oldRoots[i]);
}
@ -100,6 +100,34 @@ export function main() {
expect(component.injector.get('hello')).toEqual('component');
})));
it('should bootstrap a component with a custom selector',
async(inject([ApplicationRef, Compiler], (app: ApplicationRef, compiler: Compiler) => {
@Component({
selector: 'bootstrap-app',
template: '',
})
class SomeComponent {
}
@NgModule({
providers: [{provide: 'hello', useValue: 'component'}],
declarations: [SomeComponent],
entryComponents: [SomeComponent],
})
class SomeModule {
}
createRootEl('custom-selector');
const modFactory = compiler.compileModuleSync(SomeModule);
const module = modFactory.create(TestBed);
const cmpFactory =
module.componentFactoryResolver.resolveComponentFactory(SomeComponent) !;
const component = app.bootstrap(cmpFactory, 'custom-selector');
// The component should see the child module providers
expect(component.injector.get('hello')).toEqual('component');
})));
describe('ApplicationRef', () => {
beforeEach(() => { TestBed.configureTestingModule({imports: [createModule()]}); });

View File

@ -131,7 +131,7 @@ export declare abstract class ApplicationRef {
readonly abstract isStable: Observable<boolean>;
readonly abstract viewCount: number;
abstract attachView(view: ViewRef): void;
abstract bootstrap<C>(componentFactory: ComponentFactory<C> | Type<C>): ComponentRef<C>;
abstract bootstrap<C>(componentFactory: ComponentFactory<C> | Type<C>, rootSelectorOrNode?: string | any): ComponentRef<C>;
abstract detachView(view: ViewRef): void;
abstract tick(): void;
}