'rxjs6 - TypeError: Cannot read property 'pipe' of undefined

After migrating from RxJs 5 beta version to RxJs 6 getting below error -

ERROR TypeError: Cannot read property 'pipe' of undefined at Object.get [as selectedTimecard]

This is my latest code after migration

import {
  combineLatest as observableCombineLatest,
  Subscription,
  Observable
} from 'rxjs';

import {
  filter,
  take
} from 'rxjs/operators';

import Timecard from './../models/timecard';
import * as fromRoot from '../reducers';

@Component({
  selector: 'gte-timecards-overview-page',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
			<gte-timecard-week
				*ngIf="(hasTimecards$ | async) && !! (selectedTimecard$ | async)"
				[timecard]="selectedTimecard$ | async"
				[editable]="true"
				[hasPictureBackground]="true"
				[user]="user$ | async"
				(onCreateNewEntry)="createEntry($event)"
				(onEdit)="editEntry($event)"
				(onUpdateDay)="updateDay($event)"
				(onDeleteEntry)="deleteEntry($event)"
				(onCopyEntry)="copyEntry($event)">
			</gte-timecard-week>
		  `,
})
export class TimecardsOverviewPageComponent {
  @ViewChild('footerActions') footerActions;
  // User state
  user$: Observable < User > ;

  // Timecards state
  selectedTimecard$: Observable < Timecard > ;
  rawSelectedTimecard$: Observable < Timecard > ;

  routerSubscription: Subscription;
  requiresChangesCheck = true;
  selectedTimecardSate: string;

  constructor(private store: Store < fromRoot.State > , private router: Router, private translate: TranslateService) {
    this.user$ = store.select(fromRoot.getActiveUser);
    this.rawSelectedTimecard$ = store.select(fromRoot.getSelectedTimecard).pipe(filter(timecard => timecard !== null));

    // Add user depending fields to selected timecard
    this.selectedTimecard$ = Observable.combineLatest(this.user$, this.rawSelectedTimecard$, (user, timecard) => {
      if (!user || !timecard) {
        return;
      }
      let selected = null;
      if (!timecard.ID.includes('newTimecard')) {
        selected = timecard.clone();
        // Set user to selected timecard as owner
        selected.owner = user;

        // Set default settings for day settings
        let days = selected.days.map(day => {
          let newDay = day.clone();
          // TODO: set defaut values from API
          let defaultArrival = moment(day.date).set('hours', 9).set('minutes', 30);
          let defaultDeparture = moment(day.date).set('hours', 17).set('minutes', 50);
          let defaultBreakDuration = moment.duration(1, 'hours');
          let defaultBreakTaken = true;

          if (user.hasArrivalTimeSettings()) {
            newDay.arrivalTime = day.arrivalTime ? moment(day.arrivalTime) : defaultArrival;
            newDay.departureTime = day.departureTime ? moment(day.departureTime) : defaultDeparture;
            newDay.breakDuration = (day.breakDuration && moment.isDuration(day.breakDuration)) ? day.breakDuration : defaultBreakDuration;
            newDay.breakTaken = null;
          } else if (user.hasBreakTakenSettings()) {
            newDay.arrivalTime = null;
            newDay.departureTime = null;
            newDay.breakDuration = null;
            newDay.breakTaken = day.breakTaken !== null ? day.breakTaken : defaultBreakTaken;
          } else {
            newDay.arrivalTime = null;
            newDay.departureTime = null;
            newDay.breakDuration = null;
            newDay.breakTaken = null;
          }

          return newDay;
        });
        selected.days = days;
      }
      return selected;
    });
  }

  saveTimecard() {
    let selectedTimecard = this.selectedTimecard;
    this.footerActions.submitCard = false;
    if (this.pastTimecard !== null && this.footerActions.savePastTimecard) {
      this.footerActions.savePastTimecard = false;
      this.store.dispatch(new timecard.SaveAction(this.pastTimecard));
    } else {
      this.store.dispatch(new timecard.SaveAction(selectedTimecard));
    }
  }

  get selectedTimecard(): Timecard {
    let timecard: Timecard;
    console.log("selectedtcobs", this.selectedTimecard$)
    this.selectedTimecard$.pipe(take(1)).subscribe(selected => timecard = selected);

    return timecard;
  }
}

In selectedTimecard(), selectedTimecard$ objservable is causing issue while using pipe/take operations.

Please help us in resolving this issue.



Solution 1:[1]

We tried placing try, catch blocks as below and it worked.

get selectedTimecard(): Timecard {
  try {
    let timecard: Timecard;
    console.log("selectedtcobs", this.selectedTimecard$)
    this.selectedTimecard$.pipe(take(1)).subscribe(selected => timecard=selected);
    return timecard;
  } catch (error) {
  }
}

But we feel this might be wrong as we are not going to handle this exception.

Please anyone have any any suggestions let us know.

Thanks, Anil

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AnilPandiya