Quiero realizar un seguimiento cuando cambia el valor de una entrada y solo cuando el elemento está borroso quiero que se active la suscripción.
Por supuesto que podría hacer algo como lo que tengo a continuación, pero eso, por supuesto, no es muy elegante. ¿Alguna sugerencia?
fromEvent(inputElement, 'input) .subscribe((e) => { fromEvent(inputElement, 'blur') .subscribe((blurEv) => { // Do something with inputElement.value }); });Supongo que podría simplemente escuchar el evento de desenfoque, pero todavía hay ciertas circunstancias en las que necesitaría realizar un seguimiento de los cambios de entrada de minutos antes de que ocurra el desenfoque.
Puede configurar la opción updateOn para blur , luego form.valueChanges solo se emitirá cuando un campo esté borroso:
export class AppComponent { form = this.fb.group({ name : '', age : '', email : '' }, { updateOn: 'blur' }); subscription = this.form.valueChanges.subscribe( value => console.log('>>> value on blur:', value) ); constructor(private fb: FormBuilder) { } }Aquí hay una demostración básica de StackBlitz .
Primero, nunca debe suscribirse dentro de una suscripción. Puede usar operadores de aplanamiento observables como concatMap , mergeMap y switchMap . Así que lo más fácil que puedes hacer es arreglar eso.
fromEvent(inputElement, 'input').pipe( switchMap(() => fromEvent(inputElement, 'blur')) ).subscribe((blurEv) => { // Do something with inputElement.value });Honestamente, es difícil pensar en algo mejor a menos que no sepas más sobre tus necesidades. El único problema con esto es que la suscripción al evento se creará después de cada entrada. Puede resolver eso con fusionar y escanear si necesita mantener un estado.
Los siguientes usos se fusionan para suscribirse a eventos de enfoque y desenfoque solo una vez. Cuando está enfocado, se emite un objeto con una propiedad oldval , y cuando está borroso, se emite un objeto con una propiedad newval . Las emisiones se fusionan con el estado anterior mediante el escaneo para crear un nuevo estado. Esto tendrá el efecto de crear un objeto con propiedades oldval y newval que se pueden comparar.
merge( fromEvent(el, 'focus').pipe(map(x => ({ oldval: el.value, state: 'hasfocus' }))), fromEvent(el, 'blur').pipe(map(x => ({ newval: el.value, state: 'lostfocus' }))) ).pipe( scan((acc, cur) => ({ ...acc, ...cur }), {}), filter(x => x.state === 'lostfocus') ).subscribe(/* Do something */);Prueba esto:
const blur$ = fromEvent(trackedEl, 'blur').pipe(take(1)) fromEvent(trackedEl, 'input').pipe( distinctUntilChanged(), switchMap(() => blur$) ).subscribe((v) => { // Do work })