ngneat / from-event

🦊 ViewChild and FromEvent β€” a Match Made in Angular Heaven

Home Page:https://netbasal.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MIT commitizen PRs styled with prettier All Contributors ngneat

ViewChild and FromEvent β€” a Match Made in Angular Heaven

Turn ViewChild and ContentChild queries into an RxJS stream.

Installation

npm install @ngneat/from-event

Usage

Use the FromEvent decorator with ViewChild or ContentChild. Note that it expects to get ElementRef.

import { FromEvent } from '@ngneat/from-event';

@Component({
  selector: 'my-btn',
  template: `
    <button #button>
      <ng-content></ng-content>
    </button>
  `
})
class ButtonComponent implements AfterViewInit {
  @FromEvent('click')
  @ViewChild('button') 
  click$: Observable<MouseEvent>;

  ngAfterViewInit() {
    this.click$.subscribe(console.log);
  }
}

You are not limited to use it only inside AfterViewInit or AfterContentInit:

@Component({
  template: `
    <button #plus>+1</button>
    <button #minus>-1</button>
    <button #reset>Reset</button>
    {{ counter$ | async }}
  `,
})
export class CounterComponent {
  @FromEvent('click')
  @ViewChild('plus')
  plus$: Observable<MouseEvent>;

  @FromEvent('click')
  @ViewChild('minus')
  minus$: Observable<MouseEvent>;

  @FromEvent('click')
  @ViewChild('reset')
  reset$: Observable<MouseEvent>;

  count$ = merge(
    this.plus$.pipe(mapTo(1)), 
    this.minus$.pipe(mapTo(-1))
  ).pipe(
    startWith(0),
    scan((acc, curr) => acc + curr)
  );

  counter$ = this.reset$.pipe(
    startWith(null),
    switchMap(() => this.count$)
  );
}

A common example is using it with switchMap():

import { FromEvent } from '@ngneat/from-event';

@Component({
  selector: 'my-comp',
  template: `
    <button #trigger>Trigger</button>
  `
})
class MyComponent implements AfterViewInit {
  @FromEvent('click')
  @ViewChild('trigger') 
  trigger$: Observable<MouseEvent>;

  ngAfterViewInit() {
    this.trigger$.pipe(switchMap(() => service.doSomething())).subscribe(result => {
      // Do something with the result
    });
  }
}

Use the FromEvents decorator with ViewChildren or ContentChildren. Note that it expects to get ElementRef.

import { FromEvents } from '@ngneat/from-event';

@Component({
  template: `
    <my-btn id="1">Click One</my-btn>
    <my-btn id="2">Click Two</my-btn>
    <my-btn id="3">Click Three</my-btn>
  `
})
class HostComponent implements AfterViewInit, OnDestroy {
  @FromEvents('click')
  @ViewChildren(ButtonComponent, { read: ElementRef }) 
  clicks$: Observable<MouseEvent>;

  ngAfterViewInit() {
    this.clicks$.subscribe(e => console.log(e.target));
  }
}

Have fun, and don't forget to unsubscribe. If you work with Ivy, you can do it with until-destroy.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Netanel Basal

πŸ’»

Toni Villena

πŸ’» πŸ’‘

This project follows the all-contributors specification. Contributions of any kind welcome!

About

🦊 ViewChild and FromEvent β€” a Match Made in Angular Heaven

https://netbasal.com

License:MIT License


Languages

Language:TypeScript 86.7%Language:JavaScript 11.0%Language:HTML 2.1%Language:CSS 0.2%