简体   繁体   中英

Angular observable with async pipe

I'm creating my first Angular app and I'm struggling with observables (surprise, surprise). I have this in my HTML tag:

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

where I try to use async pipe with my observable. In order to update value of my observable I make some REST calls (after user clicks a button) and here is how I handle the click:

  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();
      });
  }

I was trying to reproduce behaviour described here: https://malcoded.com/posts/angular-async-pipe/ How I understand what's going on in my code: after getting response body from REST call I update next value which behaviourSubject will have. Then I create a new observable with the next value already set to my desired response. Then I update my observable in HTML. HTML should be reloaded (because it listens for value change and value of my observable just changed). New value from my REST call should be visible in HTML. What am I missing?

I believe you're trying to pass your observable via an input and I'm not sure that change will be detected and send. What I would suggest is to store your observable into your service so it's possible to get it via dependency injection.

Here's an example showing you how to use a subject (I suggest BehaviorSubject). You can then inject your service in your calandar month view component and use your observable there. (FYI: standard for an observable is to add a $ at the end so you know it's one)

@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);
      })
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM