File tree Expand file tree Collapse file tree
apps/rxjs/49-hold-to-save-button/src/app Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1- import { ChangeDetectionStrategy , Component } from '@angular/core' ;
1+ import { ChangeDetectionStrategy , Component , signal } from '@angular/core' ;
2+ import { HoldableDirective } from './holdable.directive' ;
23
34@Component ( {
4- imports : [ ] ,
5+ imports : [ HoldableDirective ] ,
56 selector : 'app-root' ,
67 template : `
78 <main class="flex h-screen items-center justify-center">
89 <div
910 class="flex w-full max-w-screen-sm flex-col items-center gap-y-8 p-4">
1011 <button
11- class="rounded bg-indigo-600 px-4 py-2 font-bold text-white transition-colors ease-in-out hover:bg-indigo-700">
12+ class="cursor-pointer rounded bg-indigo-600 px-4 py-2 font-bold text-white transition-colors ease-in-out hover:bg-indigo-700"
13+ holdable
14+ [duration]="2000"
15+ (complete)="onSend()"
16+ (progressUpdated)="progress.set($event)">
1217 Hold me
1318 </button>
1419
15- <progress [value]="20 " [max]="100"></progress>
20+ <progress [value]="progress() " [max]="100"></progress>
1621 </div>
1722 </main>
1823 ` ,
1924 changeDetection : ChangeDetectionStrategy . OnPush ,
2025} )
2126export class AppComponent {
27+ progress = signal ( 0 ) ;
28+
2229 onSend ( ) {
2330 console . log ( 'Save it!' ) ;
2431 }
Original file line number Diff line number Diff line change 1+ import {
2+ Directive ,
3+ ElementRef ,
4+ inject ,
5+ input ,
6+ OnDestroy ,
7+ OnInit ,
8+ output ,
9+ } from '@angular/core' ;
10+ import {
11+ filter ,
12+ fromEvent ,
13+ interval ,
14+ map ,
15+ merge ,
16+ Subscription ,
17+ switchMap ,
18+ take ,
19+ takeUntil ,
20+ tap ,
21+ } from 'rxjs' ;
22+
23+ @Directive ( { selector : '[holdable]' } )
24+ export class HoldableDirective implements OnInit , OnDestroy {
25+ duration = input . required < number > ( ) ;
26+ complete = output < void > ( ) ;
27+ progressUpdated = output < number > ( ) ;
28+
29+ private elementRef = inject ( ElementRef ) ;
30+ private sub : Subscription | null = null ;
31+
32+ ngOnInit ( ) {
33+ const element = this . elementRef . nativeElement as HTMLElement ;
34+ const resetEvents$ = merge (
35+ fromEvent ( element , 'mouseup' ) ,
36+ fromEvent ( element , 'mouseleave' ) ,
37+ ) ;
38+
39+ this . sub = fromEvent ( element , 'mousedown' )
40+ . pipe (
41+ switchMap ( ( ) => {
42+ return interval ( 10 ) . pipe (
43+ takeUntil ( resetEvents$ ) ,
44+ map ( ( value ) => ( value + 1 ) * 10 ) ,
45+ tap ( ( value ) => {
46+ const progress = Math . round ( ( value / this . duration ( ) ) * 100 ) ;
47+ this . progressUpdated . emit ( progress ) ;
48+ } ) ,
49+ filter ( ( value ) => value >= this . duration ( ) ) ,
50+ take ( 1 ) ,
51+ tap ( ( ) => {
52+ this . complete . emit ( ) ;
53+ } ) ,
54+ ) ;
55+ } ) ,
56+ )
57+ . subscribe ( ) ;
58+ }
59+
60+ ngOnDestroy ( ) {
61+ this . sub ?. unsubscribe ( ) ;
62+ }
63+ }
You can’t perform that action at this time.
0 commit comments