Reputation: 2270
I'm building modal service in angular 2. I resolve most of the issues but i have problem placing the modal component in the body element in a nice angular way. I use DynamicComponentLoader.loadNextToLocation
function to get the modal component and place it next to the ElementRef
that is uset in DynamicComponentLoader.loadNextToLocation
function. But when i don't want to place the created modal inside some component i have to manipulate DOM to insert the created modal. My question is can i use the root element in my application in the modal service? I want to achieve this when specific element isn't provided as container for the modal.
var elementRef = DOM.query('app');
this.componentLoader.loadNextToLocation(ModalBackdrop, elementRef, backdropBindings)
Upvotes: 8
Views: 25354
Reputation: 21
Add a reference for ElementRef in your component's constructor:
constructor (private applicationRef: ApplicationRef) { }
You can get ElementRef with either two ways:
let container : HTMLElement;
1) container = this.applicationRef.components[0].location.nativeElement
or
2) let viewContainer = this.applicationRef.components[0];
container = (viewContainer.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
Upvotes: 1
Reputation: 52867
To get a reference to the root component, you can inject ApplicationRef:
constructor(private app:ApplicationRef)
{
let element: ElementRef = this.app['_rootComponents'][0].location;
}
Upvotes: 9
Reputation: 40936
The available answers didn't work for me:
In my situation, I am developing a 3rd party library so I cannot make any assumption that the root is called AppComponent or that it has ElementRef injected. This is what worked for me (Angular 6.1)
private readonly rootRef: ElementRef;
constructor(private appRef: ApplicationRef) {
this.rootRef = appRef.components[0].injector.get(ElementRef);
}
I later discovered that if I tried to inject and use the service very early after Angular bootstraps, an exception was thrown because appRef.components
is still empty. So I instead modified the code to make rootRef
a promise that resolves with ElementRef
. This way the consuming code can call it immediately without raising an exception but will have to wait for the ElementRef
to resolve:
private readonly rootRef: Promise<ElementRef>;
constructor(appRef: ApplicationRef) {
this.rootRef = new Promise(resolve => {
setTimeout(
() => resolve(appRef.components[0].injector.get(ElementRef)),
100
);
});
}
Upvotes: 2
Reputation: 3258
This works in Angular 5.2.9
Add a public ElementRef in your root component's constructor:
export class AppComponent {
constructor (public eltRef: ElementRef) { }
And in the component where you want to access the root, do this:
private rootRef: ElementRef;
constructor(private appRef: ApplicationRef) {
this.rootRef = (this.appRef.components[0].instance as AppComponent).eltRef;
}
Upvotes: 1
Reputation: 658067
appElementRef: ElementRef;
constructor(private applicationRef:ApplicationRef, injector: Injector) {
this.appElementRef = injector.get(applicationRef.componentTypes[0]).elementRef;
}
The AppComponent
would need to provide the elementRef
field that returns the ElementRef
though.
See also https://github.com/angular/angular/issues/6446
Upvotes: 8
Reputation: 1538
The problem is that to get the root ElementRef, your application should be bootstrapped. And in some situations (getting ElementRef in services) we should wait for that. My solution:
import {Injectable, ApplicationRef, ElementRef} from 'angular2/core';
@Injectable()
export class SomeService {
private _appElementRef: ElementRef;
constructor(appRef: ApplicationRef) {
appRef.registerBootstrapListener(appComponentRef => {
this._appElementRef = appComponentRef.location;
});
}
}
Upvotes: 1