Home > Back-end >  How to skip first value of an observable with RxJS?
How to skip first value of an observable with RxJS?

Time:10-01

In my Angular project I use this component what is replresent an input field in a form. The goal is to save the value of the input field on-the-fly if user changed it:

export class SettingInputComponent implements OnInit, OnDestroy {
  @Input() model: SettingInterface;

  private subscriptions: Subscription = new Subscription();

  private appDataService: AppDataServiceInterface<SettingInterface> =
    new AppDataFactoryService<SettingInterface>().get(Setting);

  private value$: BehaviorSubject<any> = new BehaviorSubject(this.model.value);

  constructor() { }

  ngOnInit(): void {
    this.subscriptions.add(this.saveSetting().subscribe());
  }

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

  emitToSave(): void {
    this.value$.next(this.model.value);
  }

  private saveSetting(): Observable<any> {
    return this.value$.pipe(
      debounceTime(500),

      distinctUntilChanged(),

      switchMap(() => this.appDataService.save(this.model)
    );
  }
}

HTML:

<third-party-input
  type="text"
  [value]="model.value"
  (change)="emitToSave()"
></third-party-input>

The problem is when the component initializing the saveSetting() observable will fire. I want to avoid this behavior and fire only when user change the model's value property.

How can I avoid the firing on initialization and fireing only when user change the value?

CodePudding user response:

I think skip method would help here

Example

const { of, iif, pipe , BehaviorSubject, Subscription, operators: { distinctUntilChanged, skip, switchMap, debounceTime } } = rxjs;

const value$ = new BehaviorSubject("initial");
const model = {}

const appDataService = {
    save(model) {      
      return of(model);
    }
}

const saveSetting = () => value$.pipe(
      skip(1),
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((model) => appDataService.save(model))
    );

saveSetting().subscribe(console.log);

setInterval(() => {
value$.next(Math.random().toString());
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>

CodePudding user response:

I think u can maintain a boolean flag along with filter operator initially it will true and with the change it will become false.

private isFirstTime = true;

ngOnInit(): void {
  this.subscriptions.add(this.saveSetting().subscribe());
}
 
emitToSave(): void {
 this.isFirstTime = false;
 this.value$.next(this.model.value);
} 

private saveSetting(): Observable<any> {
 return this.value$.pipe(
   filter(_ => !isFirstTime)
   debounceTime(500),
   distinctUntilChanged(),
   switchMap(() => this.appDataService.save(this.model)
 );
}
  • Related