Передайте значение BehaviorSubject в качестве параметра - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть угловой компонент с BehaviourSubject, инициализированным на текущий месяц:

textLabel: string;

private monthIndex$: BehaviorSubject<number>;

private MONTHS = [
"Gennaio",
"Febbraio",
"Marzo",
"Aprile",
"Maggio",
"Giugno",
"Luglio",
"Agosto",
"Settembre",
"Ottobre",
"Novembre",
"Dicembre"
];

constructor(private listService: ShoppingListService) {}

ngOnInit() {
  this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());

  // Like this it does not display the label
  this.setMonthLabel(this.monthIndex$.value); 

  this.model$ = this.monthIndex$.pipe(
    switchMap((monthValue: number) => {
      //    this.setMonthLabel(monthValue);  // This way it works!
      return this.listService.getHistoryChartModel(monthValue);
    }),
    takeUntil(this.destroy$)
  );
}

private setMonthLabel(monthIndex: number) {
  this.textLabel = this.MONTHS[monthIndex];
}

setMonth(direction: number) {
  let monthIndex = this.monthIndex$.getValue();
  monthIndex += direction;
  monthIndex =
  monthIndex < 0 ? 0 : monthIndex > 11 ? 11 : monthIndex;

  this.monthIndex$.next(monthIndex);
  this.setMonthLabel(monthIndex);
}

И шаблон:

<div class="view-sel-container">
  <button
   color="primary" mat-icon-button
   (click)="setMonth(-1)"
   [disabled]="monthIndex === 0">
  <i class="material-icons">
    keyboard_arrow_left
  </i>
 </button>

 <span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>

 <button
  color="primary" mat-icon-button
  (click)="setMonth(1)"
  [disabled]="monthIndex === 11">
  <i class="material-icons">
    keyboard_arrow_right
  </i>
 </button>

Это причина синхронизациипочему при передаче значения BehavourSubject методу this.setMonthLabel(this.monthIndex$.value) метка не отображается в шаблоне?

ОБНОВЛЕНИЕ

Решение, предоставленное Деборой Курата с использованием get /установить вместо BehaviourSubject это лучший способ пойти.Я оставляю исходный вопрос / код открытым, так как до сих пор не понимаю, почему код теперь работает, передавая значение поведенческого объекта в качестве параметра.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Подумайте о том, чтобы сделать что-то подобное, не требующее Subject или BehaviorSubject:

Компонент

import { Component } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
  templateUrl: './history-chart.component.html'
})
export class HistorChartComponent {
  textLabel: string;
  model$: Observable<any>;

  private _monthIndex: number;
  get monthIndex(): number {
    return this._monthIndex;
  }
  set monthIndex(value: number) {
    console.log("setter called with: " + value);
    // Set the label
    this.setMonthLabel(value);
    // Get the data
    this.getMonthData(value);
    this._monthIndex = value;
  }

  private MONTHS = [
    "Gennaio",
    "Febbraio",
    "Marzo"
  ];

  constructor() { }

  ngOnInit() {
    // This calls the setter
    this.monthIndex = new Date().getMonth();
  }

  // Increment or decrement the month index
  // This calls the setter
  setMonth(value: number) {
    this.monthIndex += value;
  }

  private setMonthLabel(monthIndex: number) {
    this.textLabel = this.MONTHS[monthIndex];
  }

  private getMonthData(monthIndex: number): void {
    // Commented out because I don't have the service code
    //this.model$ = this.listService.getHistoryChartModel(monthIndex);

    // Faking out the call to the service
    this.model$ = of(
      { id: 1, value: "some data for month : " +  this.MONTHS[monthIndex] },
    );
  }
}

Сеттер автоматически вызывается каждыйвремя, когда пользователь изменяет значение ИЛИ, когда значение изменяется в коде.Так что сеттер является хорошим местом для выполнения любого кода, который должен реагировать на изменение.

С помощью приведенного выше кода данные за месяц извлекаются в ngOnInt И каждый раз, когда пользователь нажимает любую из кнопок.Если вы не видите такого поведения с предоставленным стеком стека, пожалуйста, дайте мне знать.

Шаблон

<div class="view-sel-container">
    <button
   color="primary" mat-icon-button
   (click)="setMonth(-1)"
   [disabled]="monthIndex === 0">
  <i class="material-icons">
    keyboard_arrow_left
  </i>
 </button>

 <span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>

 <button
  color="primary" mat-icon-button
  (click)="setMonth(1)"
  [disabled]="monthIndex === 11">
  <i class="material-icons">
    keyboard_arrow_right
  </i>
 </button>

<div>
<span class="label-text" *ngIf="textLabel">
 {{textLabel}}
</span>
</div>
<div *ngIf="(model$ | async) as model">
  <div>
  {{ model.value }}
  </div>
</div>

Вот соответствующий стека блика: https://stackblitz.com/edit/angular-bpusk2

0 голосов
/ 19 февраля 2019
this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());

  // Like this it does not display the label
  this.setMonthLabel(this.monthIndex$.value); 

  this.model$ = this.monthIndex$.pipe(
    tap(monthValue => {
      this.setMonthLabel(monthValue);
      return this.listService.getHistoryChartModel(monthValue);
    }),
    takeUntil(this.destroy$)
  );
  1. Вы должны использовать tap для всего, что является побочным эффектом.
  2. Я не знаю, почему вам нужно было бы использовать this.setMonthLabel(this.monthIndex$.value), когда у вас уже есть значение в вашей трубе?
  3. Что делает this.setMonthLabel?
...