In Angular the most common and easy practice to handle HTML event, it is a simple event binding, but when logic become more complex, it is rational to use RxJS operators.
Let's see at two boilerplate examples:
@Component({
selector: 'app-native-handler',
template: `
<ul>
<li *ngFor="let user of users">{{ user }}</li>
</ul>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<label>
Name:
<input type="text" formControlName="name">
</label>
<input type="submit" [disabled]="form.invalid">
</form>
`,
styleUrls: ['./native-handler.component.css']
})
class NativeHandlerComponent implements OnInit {
form = new FormGroup({
name: new FormControl('', Validators.required)
});
users: string[] = ['Foo', 'Bar', 'Baz'];
constructor() {}
ngOnInit() {}
onSubmit() {
let name = this.form.controls.name.value;
this.users.push(name);
this.form.reset();
}
}
@Component({
selector: 'app-rxjs-handler',
template: `
<ul>
<li *ngFor="let user of users">{{ user }}</li>
</ul>
<form #formEl [formGroup]="form">
<label>
Name:
<input type="text" formControlName="name">
</label>
<input type="submit" [disabled]="form.invalid">
</form>
`,
styleUrls: ['./rxjs-handler.component.css']
})
class RxjsHandlerComponent implements OnInit, AfterViewInit {
@ViewChild('formEl') formEl: ElementRef;
form = new FormGroup({
name: new FormControl('', Validators.required)
});
users: string[] = ['Foo', 'Bar', 'Baz'];
constructor() {}
ngOnInit() {}
ngAfterViewInit() {
fromEvent(this.formEl.nativeElement, 'submit')
.pipe(tap(() => this.onSubmit()))
.subscribe();
}
onSubmit() {
let name = this.form.controls.name.value;
this.users.push(name);
this.form.reset();
}
}
In the first example, we don't have flexibility to do an extra async operations, unless we won't create another Observable inside onSubmit() function and subscribe to it double (first time when we do the event binding and second when we subscribe inside onSubmit() function).
On another hand, in the second example, we can pipe() whatever async strategy we want (switchMap, concatMap, mergeMap and etc) and we don't need to create any extra Observable. For example:
fromEvent(this.formEl.nativeElement, 'submit')
.pipe(
takeUntil(this.unsubscribe$),
tap(() => this.onSubmit()),
concatMap(() => this.http.post('/api/user', { name })),
concatMap(() => this.storageSerivce.push(name)),
catchError(...)
...
)
.subscribe()
So my question is, is fromEvent function better than the event binding? Is it readable enough? Is it used commonly or do you think it should be used commonly (at least when logic become complex)?
In another words, is it best practice?