Angular наблюдаемый с помощью async pipe

Я создаю свое первое приложение Angular, и я борюсь с наблюдаемыми (сюрприз, сюрприз). У меня есть это в моем HTML-теге:

  <mwl-calendar-month-view
    *ngSwitchCase="'month'"
    [viewDate]="viewDate"
    [events]="observable | async"
    [activeDayIsOpen]="true"
  >

где я пытаюсь использовать асинхронный канал с моим наблюдаемым. Чтобы обновить значение наблюдаемого, я делаю несколько вызовов REST (после того, как пользователь нажимает кнопку), и вот как я обрабатываю щелчок:

  observable: Observable<CalendarEvent[]>;
  behaviourSubject: BehaviorSubject<CalendarEvent[]> = new BehaviorSubject([{
    title: 'title12345',
    start: new Date(),
    end: new Date()
  }]);

(...)

  onCreateCalendarEventClick() {
    let calendarEvent: CalendarEvent;
    calendarEvent = {
      title: (document.getElementById('calendarEventName') as HTMLInputElement).value,
      start: new Date((document.getElementById('calendarEventStartDate') as HTMLInputElement).value),
      end: new Date((document.getElementById('calendarEventEndDate') as HTMLInputElement).value),
      color: undefined
    };
    let calendarEventApi: CalendarEventApi;
    let calendarEventColor;
    if (calendarEvent.color) {
      calendarEventColor = calendarEvent.color;
    }
    calendarEventApi = {
      title: calendarEvent.title,
      start: ToApiMapper.formatDateTimeToApi(calendarEvent.start),
      end: ToApiMapper.formatDateTimeToApi(calendarEvent.end),
      color: ToApiMapper.mapColorToApi(calendarEventColor)
    };
    this.calendarService.saveCalendarEvent(calendarEventApi).subscribe( () => {
      this.fetchCalendarData();
    }, error => {
      this.alertService.displayAlert('saving calendar event failed: ' + error);
    });
  }


  private fetchCalendarData() {
      const calendarEvents: CalendarEvent[] = [];
      this.calendarService.fetchCalendarData(this.userService.getLoggedUser()).subscribe(calendarEventsApi => {
        calendarEventsApi.forEach(calendarEventApi => {
          const calendarEvent: CalendarEvent = {
            title: calendarEventApi.title,
            start: new Date(calendarEventApi.startDate),
            end: new Date(calendarEventApi.endDate),
            color: {
              primary: calendarEventApi.eventColour,
              secondary: calendarEventApi.eventColour
            }
          };
          calendarEvents.push(calendarEvent);
        });
        this.behaviourSubject.next(calendarEvents);
        this.observable = this.behaviourSubject.asObservable();
      });
  }

Я пытался воспроизвести поведение, описанное здесь: https://malcoded.com/posts/angular-async-pipe/ Как я понимаю, что происходит в моем коде: после получения тела ответа от вызова REST я обновляю следующее значение, которое будет иметь behaviorSubject. Затем я создаю новый наблюдаемый объект со следующим значением, уже установленным для моего желаемого ответа. Затем я обновляю наблюдаемое в HTML. HTML должен быть перезагружен (потому что он прослушивает изменение значения, а значение моего наблюдаемого только что изменилось). Новое значение из моего вызова REST должно быть видно в HTML. Что мне не хватает?


person Dahaka    schedule 21.10.2020    source источник


Ответы (1)


Я считаю, что вы пытаетесь передать наблюдаемое через ввод, и я не уверен, что изменение будет обнаружено и отправлено. Я бы посоветовал сохранить наблюдаемое в вашем сервисе, чтобы его можно было получить с помощью инъекции зависимостей.

Вот пример, показывающий, как использовать тему (я предлагаю BehaviorSubject). Затем вы можете внедрить свой сервис в свой компонент просмотра календарного месяца и использовать там свой наблюдаемый объект. (К вашему сведению: стандарт для наблюдаемого - добавить $ в конце, чтобы вы знали, что это один)

@Injectable({
  providedIn: 'root'
})
export class UserService {

  private userList: User[];
  private userListSubject: BehaviorSubject<User[]> = new BehaviorSubject<User[]>([]);

  public constructor(private http: HttpClient) { }

  public usersList$(): Observable<User[]> {
    return this.userListSubject.asObservable();
  }

  public getAll$(): Observable<User[]> {
    return this.http.get<User[]>('/api/users').pipe(
      tap(userList => {
        this.userList = userList;
        this.userListSubject.next(this.userList);
      })
    );
  }
}
person Leccho    schedule 21.10.2020
comment
Я не понимаю, почему вы перешли с подписки в моем подходе на pipe + tap в вашем, но теперь я не могу правильно отлаживать внутри лямбда-выражения крана (отладчик не входит в это место - я могу останавливаться только на точках останова после того, как кран и канал закончены). Я использовал usersList $ () | async в HTML, и после обработки тела ответа от вызова REST ничего не происходит. Правильно ли мой подход с использованием Observable, BehaviorSubject и async pipe? Или это можно сделать другим, более доступным способом? - person Dahaka; 22.10.2020
comment
Вам нужно добавить private userService: UserService в свой mwl-calendar-month-view. Как только это будет сделано, вы можете в этом компоненте использовать userList$(). Затем вам также нужно использовать alteast один раз в вашем приложении this.getAll().subcribe(), чтобы загрузить данные в вашу службу. Если я использую pipe + tap, это потому, что когда я использую getAll (), я подписываюсь, и это позволяет мне выполнять действия и там. Если вы не подписываетесь на наблюдаемое, вы не будете получать данные. Если вы используете Observable, BehaviorSubject и async pipe, он должен работать нормально. - person Leccho; 22.10.2020
comment
Я предлагаю вам найти время, чтобы прочитать официальный документ, чтобы понять, как работает наблюдаемый. rxjs-dev.firebaseapp.com/guide/overview - person Leccho; 22.10.2020