Home > Net >  Benefit of rxjs subscription form value changes
Benefit of rxjs subscription form value changes

Time:02-23

I have seen the following code elsewhere on stackoverflow:

@Component({
  selector: 'my-app',
  template: `
       <input [formControl]="control" />
       <div>{{ name$ | async | json }}</div>
   `
})
export class AppComponent implements OnInit {
  name$: Observable<string>;
  control;

  constructor(private builder: FormBuilder) {
    this.control = this.builder.control('');
  }

  ngOnInit() {
    this.control.setValue('2');
this.name$ = this.control.valueChanges
  .pipe(
    startWith(this.control.value),
    map((name) => {
      console.log('fired', name)
      return name;
    })
  );
   
  }
}

My questions are:

  1. What's the benefit of using rxjs subscription to listen to form changes when the developer could have just put (change) methods directly on the form field instead?
  2. I'm having trouble understanding as to what pipe and startWith are doing here?

CodePudding user response:

What's the benefit of using RxJs subscription to listen to form changes when the developer could have just put (change) methods directly on the form field instead?

The benefits of RxJs over the traditional (change) method are in the fact if you want to apply some additional transformations or RxJs utilities such as skip, take etc.

A few examples:

distinctUntilChanged: which only emits when the current value is different from the previous value.

debounceTime allows you to ignore events until a certain silent period is maintained between your events.

I'm having trouble understanding what pipe and startWith are doing here?

pipe operator is used when you apply multiple RxJs operators on your Observable Stream. For example, I have an input where I want to have a 1-second delay between each stroke, and the input should be distinct. I would have to use the pipe operator to merge those different RxJs operators, Think of a pipe as an assembly line in a factory in which the product(Observable Stream) goes through and comes out as a finished product(value/response) in the end.

 this.control.valueChanges.pipe(
         debounceTime(1000), 
         distinctUntilChanged()
         ).subscribe(value => {
             // Your code here
         }); 

startWith is an operator that tells your pipe operator to start the observable stream with this value. In your case being this.control.value which would be the initial value of your control

CodePudding user response:

Basically you are letting the async pipe to do all the work for you. You have an observable stored in a variable:

name$: Observable<string>;

The async pipe is subscribing and unsubscribing when necessary to that observable and expects a string to be resolved and printed in the component template.

Since you have an observable you can use the .pipe() which will let you to do additional things with the observable every time a value is emitted. In this case you are setting a default value you could say, since you set the value of control to '2' and then using the pipe you are forcing the first value of the stream to be the '2' that you have set before.

Finally that map operator is not really doing nothing but printing a console.log

EDIT: Every time a new value is emitted to the observer the pipe will be triggered, so for example with the map operator you could avoid the use of some certain strings like this:

ngOnInit() {
    var restrictedWords: string[] = ['word', 'bad'];
    this.control.setValue('2');
    this.name$ = this.control.valueChanges.pipe(
      startWith(this.control.value),
      map((value: string) => {
        if (restrictedWords.indexOf(value) !== -1) {
          this.control.setValue('');
          return '';
        } else {
          return value;
        }
      })
    );
  }

As you can see if you type some string included in the restrictedWords array then automatically the value will be set to an empty string. This is just an example you can do whatever you want

  • Related