How to target an HTML element using rxjs fromEvent in Angular 6

10,764

Solution 1

You can give the input field that you want to observe, a template variable.

You can use then use @ViewChild to get access to that input. And then use the nativeElement property on it.

Now the nativeElement property will only be accessible after the view has initialized. So you can use the AfterViewInit Component Lifecycle Hook in order to access it.

import { Component, ViewChild, ElementRef } from '@angular/core';
import { fromEvent } from 'rxjs';

@Component({
  selector: 'my-app',
  template: `<input #toTarget type="text">
             <input type="text">`
})
export class AppComponent {

  @ViewChild('toTarget') toTarget: ElementRef;

  ngAfterViewInit() {
    fromEvent(this.toTarget.nativeElement, 'keyup')
      .subscribe(res => console.log(res.target.value));
  }
}

Here's an Updated StackBlitz for your ref.

Solution 2

If you're reading this with Angular 8+, the correct way to reference @ViewChild-elements while being able to use them in ngOnInit is this:

import { Component, ViewChild, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { fromEvent } from 'rxjs';

@Component({
  selector: 'my-app',
  template: `
    <input #yourTarget type="text">
    <input type="text">
  `
})
export class AppComponent implements OnInit, OnDestroy {
  @ViewChild('yourTarget', {static: true}) yourTarget: ElementRef;

  subscriptions = new Subscription();

  ngOnInit(): void {
    subscriptions.add(
      fromEvent(this.yourTarget.nativeElement, 'keyup')
        .subscribe(res => console.log(res.target.value))
    )
  }

  ngOnDestroy(): void {
    subscriptions.unsubscribe();
  }
}

Notice the {static: true} inside the @ViewChild declaration: It causes Angular to know the referenced element already in the lifeCycle "OnInit".

Share:
10,764
Dhiru
Author by

Dhiru

I am a web designer and developer form Jamshedpur, India.

Updated on June 27, 2022

Comments

  • Dhiru
    Dhiru almost 2 years

    Issue

    I have used ngrx fromEvent operator to create an Observable from 2 input text fields, I have used document as target which is fine, but now I want to target only one input field. I am not sure sure what to use instead of document to target only one input field.

    What I have done so far to get the target

    • Used document.getElementByID('someID')
    • Used ElementRef
    • Used document.querySelector('someID')

    Code

    StackBlits live editor

    import { Component } from '@angular/core';
    import { fromEvent } from 'rxjs';
    
    @Component({
      selector: 'my-app',
      template: `<input type="text">
                 <input type="text">`
    })
    export class AppComponent {
      ngOnInit() {
        fromEvent(document, 'keyup')
          .subscribe(res => console.log(res.target.value));
      }
    }
    

    Thanks for your help in advance.

  • Safal Pillai
    Safal Pillai about 5 years
    @ViewChild attributes should be accessed inside ngAfterViewInit, since they are set after the view has been initialized provided the element doesn't have ngIf/ngFor directives.
  • SiddAjmera
    SiddAjmera about 5 years
    @SafalPillai, that makes sense. Thanks a lot for pointing it out. I've updated my answer. :)