简体   繁体   中英

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

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

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? CalendarEvent s or an array of CalendarEvent s?

My best guess here is to use mergeMap to output CalendarEvent s one after another as you find them. If you want the output to be an array of CalendarEvent s 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.

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