born2net
born2net

Reputation: 24993

What's the proper way of accessing native element in angular2 (2 diff ways) docs are scarce

What's the proper way of accessing native element in angular2 (2 diff ways) so I have seen code that uses:

constructor(ele: ElementRef) {
    let myEl = ele.nativeElement;
    // do some work on myEl such as jQuery(myEl).hide()
    ...

As well as code that uses native dom via BrowserDomAdapter:

constructor(viewContainer:ViewContainerRef) {
   let dom = new BrowserDomAdapter();
   let el = viewContainer.element.nativeElement; 
   let myEle = dom.getElementsByClassName(el, element)[0];
   // or jQuery(myEle).hide()
   ...

I am wondering what's the Pro / Cons and "proper" way of doing things. Unfortunately, the docs seem scarce still.

I am assuming the latter will give you WebWorkers support through the interface, but it is just my assumption.

Upvotes: 18

Views: 39366

Answers (2)

peterh
peterh

Reputation: 1

There is a (probably intentionally) undocumented feature for that. You don't have to deal with views and with injected inputelements.

Furthermore, simply giving a

constructor(private e: ElementRef)

also won't work, it will be compilable by the typescript, but it will give you a parameter error in the runtime initializaton.

Finally I could find a solution in only 3 hours of digging:

import { Component, Directive, ElementRef, Inject } from "@angular/core";

@Component({
    selector: "my-selector",
    template: "my-template"
})
export class MyComponent {
    private domNode: HTMLElement = null;
    constructor( @Inject(ElementRef) elementRef: ElementRef) {
        this.domNode = elementRef.nativeElement;
    }
}

As you can see, the constructor will get the ElementRef if and only if you have injected the parameter with an @Inject(ElementRef) keyword. Both Inject and ElementRef should be imported from the angular core.

ElementRef.nativeElement is the HTML DOM node what you are looking for. You have the chance to catch it only in the constructor, so don't miss the opportunity.

In the Angular documentation, they try to convince you that you don't need it, in their dialect it means that they admit that you need it, but they don't want you to use it.

In earlier angular versions it worked even without the @Inject thing, but fortunately the Angular development always Provides us newer and newer secrets in their otherways "stable" product.


Extension:

There was a comment (currently moved into a chatroom), it said that the @Inject annotation is not needed if you have emitDecoratorMetadata: true in your tsconfig.json. My experiences contradict this, furthermore it breaks the wall between the js and ts, but it is also a possible solution. It is possible, that the experiences of the commenter are from a previous week.

Upvotes: 4

Günter Zöchbauer
Günter Zöchbauer

Reputation: 658253

<div #foo>
@ViewChild() foo;
ngAfterViewInit(){
  foo.nativeElement...
} 

or if transcluded

@ContentChild() foo;
ngAfterContentInit(){
  foo.nativeElement...
} 

Allow to pick elements by template variable or component or directive type. (with a type you'll get the component instance instead of the element though.

or

constructor(@ViewChildren('foo') elements) {...  
constructor(@ContentChildren('foo') elements) {...  

@ViewChild provides a live view to matching elements with changes subscription.

See also

Upvotes: 25

Related Questions