Hoàng Nguyễn
Hoàng Nguyễn

Reputation: 1170

Angular 5 - How to watch data change between sibling components without refreshing page?

I have two sibling components, the first component has select box with different option bind to a variable called selectedValue. When I change the value of options in the first component, I want the same value is changed in the second component. However, the second component keeps showing undefined value. These two sibling components have ngOnInit at the same time.

Here is my code:

component1.ts:

selectedValue: any;
tokens: Tokens;

  constructor(
    private apiService: ApiService,
    private sharedService: SharedService
  ) {
  }

  ngOnInit() {
    this.loadTokens();
    this.sharedService.pair.next(this.selectedValue);
  }

  loadTokens() {
    this.apiService.getTokens()
    .subscribe((data: any) => {
      this.tokens = data;
    }, error => {
      console.log(error);
    });
  } 

component1.html:

<mat-select placeholder="Choose a pair" [(ngModel)]="selectedValue">
  <mat-option>-- None --</mat-option>
  <mat-option *ngFor="let token of tokens" [value]="token.shortName">
    {{token.name}}
  </mat-option>        
</mat-select>

shared.service.ts:

@Injectable()
export class SharedService {

  pair = new BehaviorSubject(null);

  observable: Observable<any> = this.pair.asObservable();
}

component2.ts:

pair: any;

  constructor(private sharedService: SharedService) {}

  ngOnInit() {
    this.sharedService.observable.subscribe((data) => {
      this.pair = data;
      console.log(this.pair);
    });
  }

Upvotes: 0

Views: 1165

Answers (2)

Ilia Volk
Ilia Volk

Reputation: 556

You should dispatch new selectedValue value on each change. For example component1.html:

<mat-select placeholder="Choose a pair" 
            (ngModelChange)="this.sharedService.pair.next($event);"
            [(ngModel)]="selectedValue">
  <mat-option>-- None --</mat-option>
  <mat-option *ngFor="let token of tokens" [value]="token.shortName">
    {{token.name}}
  </mat-option>        
</mat-select>

Or, instead of observables, create field pair: string on service and bind it to ngModel. component1: [(ngModel)]="sharedService.pair" component2: {{sharedService.pair}}

Upvotes: 1

Chrillewoodz
Chrillewoodz

Reputation: 28338

The problem is that you call .next before a value is even set. What you should be doing is:

<mat-select placeholder="Choose a pair" [(ngModel)]="selectedValue" (ngModelChange)="emit($event)"></mat-select>

emit(selectedValue) {
  this.sharedService.pair.next(selectedValue);
}

Upvotes: 4

Related Questions