how to access Native HTML Input element using formControl in Angular 2.0

AIon picture AIon · Sep 29, 2016 · Viewed 9.3k times · Source

I'm using Angular 2.0 final release.

What i want to do? - i want to show some notifications (warnings, the requirements for the input) only when the input receive focus. Or even better, when his parent (the div) has mouse hover event.

Doing this from the parent(the div) is easy. Just (focus)=showNotifications() + an ngIf - and the job is done.

But i want to encapsulate this functionality inside the show-notifications component - and make it reusable..

Given that i pass the control inside the show-notifications using @Input() - i could do both this things if i have access to the native HTML input element.You can see how in show-notifications.component.ts. Here is the code:

app.component.html:

`<div>
   <label>Name: </label>
   <input formControlName="myName">
   <show-notifications [the_control]="myName" ></show-notifications>
</div>`

app.component.ts:

export class AppComponent {
    myName = new FormControl("defaultvalue",[some validators..])
}

show-notifications.component.html:

<div class="show_requirements" *ngIf="hasfocus or parentDivHasMouseHover"> // incorect code and logic - i know, but you can see the idea..

    <p *ngFor="let requirement of thisInputRequirements">{{requirement}}<p>

</div>

show-notifications.component.ts:

export class ShowNotificationsComponent {

    @Input() the_control;
    this.thisInputRequirements = // take them form firebase.
    this.thisInputCustomErrorMessages = // take them from firebase.

    // I implemented all this and works amazing but i want to do:

    //something like this:

    ngOnInit(){
        this.nativeInputElement = this.the_control.getNativeElement() // this of course doesn't work

        // the requirements are shown only when the input receive focus
        let source = Rx.DOM.focus(this.nativeInputElement);
        source.subscribe( x => this.hasFocus = true)

        // Or even better: 
        // the requirements are shown only when the parent has mouse hover
        // or any other event / endles posibilites here..

        let parent = getParentOf(this.nativeInputElement)
        let source = Rx.DOM.mouseover(parent);
        source.subscribe( x => this.parentDivHasMouseHover = true) // this will be some toggling functionality.
    }

}

Question:

How do i access the native element given that i have the formControl (myName = the_control) object?

Is there a better way to do notifications in a separate component - and make it reusable? I already use this successfully throughout my entire app - to show errors and input requirements..

Note: I tried to pass the hole html input first using hashtag syntax ( #myInput ) and form there, inside the show-notifications component, i tried to do: myInput.myName - to acces the control but i get undefined. The controls are not present on the native input element. And I need that control for validation:)

Answer

martin picture martin · Sep 30, 2016

I think you could use # notation to pass the element to ShowNotificationsComponent:

export class ShowNotificationsComponent {
    @Input() the_control;
    @Input() elm;
    //...
}

Then in the template:

<input formControlName="myName" #elm>
<show-notifications [the_control]="myName" [elm]="elm"></show-notifications>