I am trying to use Renderer.selectRootElement to get some elements from my Component, as described here.
Everything works fine, unless I select only one element (pln
If you want to preserve content then use the second boolean parameter to true
, like this: (using Angular 6)
let activeLi = this.renderer.selectRootElement('ul.ddl>li.active', true);
See the detail from API
/*
* Implement this callback to prepare an element to be bootstrapped
* as a root element, and return the element instance.
* @param selectorOrNode The DOM element.
* @param preserveContent Whether the contents of the root element
* should be preserved, or cleared upon bootstrap (default behavior).
* Use with `ViewEncapsulation.ShadowDom` to allow simple native
* content projection via `<slot>` elements.
* @returns The root element.
*/
abstract selectRootElement(selectorOrNode: string | any, preserveContent?: boolean): any;
Thanks Eric to bring in notice that it removes content by default!
Its purpose is not to select random elements by selector in your components view.
Simply see its implementation in DomRootRenderer
selectRootElement(selector: string): Element {
var el = DOM.querySelector(this._rootRenderer.document, selector);
if (isBlank(el)) {
throw new BaseException(`The selector "${selector}" did not match any elements`);
}
DOM.clearNodes(el);
return el;
}
Do you see something interesting there? It's removing the nodes inside the element! Why would it do that? Because its purpose it's to grab the root element! So which one is the root element? Does this sound familiar?
<my-app>
Loading...
</my-app>
Yes! That's the root element. Okay then, but what's wrong with using selectRootElement
if I only want to grab the element? It returns the element without its children and nothing changes in the view! Well, you can still use it of course, but you will be defeating its purpose and misusing it just like people do with DynamicComponentLoader#loadAsRoot
and subscribing manually to EventEmitter.
Well, after all its name, selectRootElement
, says pretty much what it does, doesn't it?
You have two options to grab elements inside your view, and two correct options.
<div #myElement>...</div>
@ViewChild('myElement') element: ElementRef;
ngAfterViewInit() {
// Do something with this.element
}
@Directive({
selector : '.inner1,inner2' // Specify all children
// or make one generic
// selector : '.inner'
})
class Children {}
template : `
<div class="container">
<div class="inner1"></div>
<div class="inner2"></div>
<!-- or one generic
<div class="inner"></div>
<div class="inner"></div>
-->
</div>
`
class Parent (
@ViewChildren(Children) children: QueryList<Children>;
ngAfterViewInit() {
// Do something with this.children
}
)