0

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

justTech
  • 25
  • 1
  • 5
  • Consider `results.map((bks: Books) => {` [... code] `} );` You're destructuring each entry in the `results` array and pulling out a `Books` object attached to a key `bks`. You've hardcoded `bks` and yet that key doesn't appear in your models anywhere. This is a bit of a code smell and perhaps the place you should start looking. – Mrk Sef Sep 28 '20 at 17:24
  • Thanks for the response I updated the question. That was an old way how I was able to map Books to Calendar Event before but was inefficient. Sorry for the confusion. 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? – justTech Sep 28 '20 at 20:01

1 Answers1

1

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.

Mrk Sef
  • 7,557
  • 1
  • 9
  • 21
  • I have to add another layer of Object.values(nameObj).flatMap(nameObj => to get the correct path However, the second flatMap is throwing Property 'flatMap' does not exist on type 'any[]' And when I change it from flatMap to map the error goes away. but then I get this error Type 'Observable' is not assignable to type 'Observable[]>'. Type '{}' is missing the following properties from type 'CalendarEvent[]': length, pop, push, concat, and 26 more.ts(2322) – justTech Sep 30 '20 at 18:23
  • What version of JavaScript are you using? As of late 2019, `flat` and `flatMap` is now published in the ECMA 2019 standard, and core-js@3 (babel's library) includes it in their polyfill library. – Mrk Sef Sep 30 '20 at 19:34
  • Maybe [this link](https://stackoverflow.com/questions/53556409/typescript-flatmap-flat-flatten-doesnt-exist-on-type-any) would help? – Mrk Sef Sep 30 '20 at 20:12
  • yea that was not the issue as I have the latest installed. However building off your first solution. the only thing stopping me from marking this as the answer is that the observable events$ is looking for a return type of CalendarEvents[]. But your suggestion returns CalendarEvents[][][] <-- nested arrays. I need to find away to get rid of those parent arrays to fit the expected observable return type – justTech Oct 03 '20 at 21:13
  • nvm was able to fix that myself by just taking the inner and reassigning it – justTech Oct 03 '20 at 21:52
  • 1
    Glad you figured it out. The reason my code had `flatMap`->`flatMap`->`map` was so that you wouldn't get nested arrays. You could just as easily call `.flat()` on the resulting nested array instead or any other method of merging nested arrays into a single array. – Mrk Sef Oct 04 '20 at 14:11