Working with observables how to map nested dynamic object keys? Using angular-calendar events

417 views Asked by At

I think maybe it would be better to use something like map<T,R> then what I'm doing currently. Hopefully, I can receive some suggestions on how to get this working. Currently the result is no events get mapped because I'm mapping incorrectly so the path is wrong.

My main issue is bks.fname is undefined as the path is wrong. The correct path is ["05182020"].Peeter.[-MCcGOMe0FT1IqvlCJkd].fname

But how would I define this in a model?

**Returned Json with each key being dynamic: **


05182020:
   Peteer:
     -MCcGOMe0FT1IqvlCJkd:   //The start of the book model
        date: "05/18/2020"
        name: "Peteer"
        service: "b"
        shop: "Howards"
        time: "10:00 AM"

The Models:

export interface Books {
    date?: string;
    fname?: string;
    lname?: string
    name?: string;
    service?: string;
    shop?: string
    time?: string;
}


export interface IDictionary<T> {
    [index:string]: Books;
}

export interface Bookings {
  [index:string]: Books;
}

export interface CalendarEvent<MetaType = any> {
    id?: string | number;
    start: Date;
    end?: Date;
    title: string;
    color?: EventColor;
    actions?: EventAction[];
    allDay?: boolean;
    cssClass?: string;
    resizable?: {
        beforeStart?: boolean;
        afterEnd?: boolean;
    };
    draggable?: boolean;
    meta?: MetaType;
}

TS NOTE: the bks.fname and others are undefined because currently map((results) => is taking in the root object instead of just the Books model.

Calaendar.component.ts

events$: Observable<CalendarEvent<IDictionary<Books>>[]>;

   this.events$ = this.fs.getFullList2(this.shopName)

      .pipe(
        catchError(err => {
          console.log(err)
          return throwError(err);
        }),
        first(),
        tap(results =>
          console.log("bookings:", results[0])
        ),
        map((results) => {
          return results.map((bks: Books) => {
           return {
              title: bks.fname + " " + bks.lname + " ---Time: " + bks.time + " , Service: " + bks.service,
              start: new Date(bks.date),
              color: colors.red,
              allDay: true,
              meta: bks,//.time,
            };
          }
          );
        }
         ));


fireserveice.ts

  getFullList2(shop: string): Observable<any> {

    return this.db.list(shop,ref=>ref.limitToFirst(1)).valueChanges()
  }

1

There are 1 answers

6
Mrk Sef On BEST ANSWER

It's sort of hard to help as your question isn't really clear. What are you expecting your output to look like? Your input is (in a round-about way) an array of books. What does this stream output? CalendarEvents or an array of CalendarEvents?

My best guess here is to use mergeMap to output CalendarEvents one after another as you find them. If you want the output to be an array of CalendarEvents you'd want to switch back to map() instead of mergeMap()

I haven't tested this at all but here's my best guess,

mergeMap(results =>
  results.flatMap(idObj =>
    Object.values(idObj).flatMap(nameObj =>
      Object.values(nameObj).map((book: Books) => ({
        title: book.fname + " " + book.lname + " ---Time: " + book.time,
        service: book.service,
        start: new Date(book.date),
        color: colors.red,
        allDay: true,
        meta: book
      }))
    )
  )
)

My hope is that you can retool this a bit so that it fits your needs.


A few things unrelated to your question, but maybe of interest.

1- This interface:

export interface IDictionary<T> {
    [index:string]: Books;
}

doesn't really make sense. You're not using the generic at all, so I wouldn't include it.

2- This interface:

export interface Bookings {
  [index:string]: Books;
}

isn't used at all in your question.

3- Your Books interface describes a single book. It's not really a problem, but it would be strange for a function to return Books but only return one book. For example

getBookById(id: number): Books {
  // some code here
}

returns a single object representing a single book, but the method signature hints that it returns multiple books.