简体   繁体   中英

Angular Observable Array Object Conversion

So I've read numerous questions on SO about item conversions in Javascript/Angular but am not finding anything that addresses my issues. I'm pulling from Firestore as an object that can have copies. I then need to convert the object using a 1 to many conversion. The object coming from Firestore is a 'MultipleCard'. This 'MultipleCard' has a property called 'copies' which will be used to signify how many 'Cards' should get created.

  postsCol: AngularFirestoreCollection<MultipleCard>;
  posts: Observable<MultipleCard[]>;

  cardsListObservable: Observable<Card[]>; //Not sure which to use
  cardsList: Card[]; //Not sure which to use

  constructor(private messageService: MessageService,
              private db: AngularFirestore) {
    this.messageService.add('Fetching cards');

    this.postsCol = this.db.collection('cards');
    this.posts = this.postsCol.valueChanges();

 //?? Nothing I do here seems to work correctly. Most operations act on the array itself or do a 1 to 1 conversion
}

Component

<mat-list *ngFor="let card of cardsList | async"> //Or cardsListObservable
  <mat-list-item>{{card.name}}</mat-list-item> 
 </mat-list>

How do I convert Observable into Observable or Card[]? For example I may have an array with the following 'MultipleCard's

 [{ id: 1,
     copies: 3},
    {id: 2, copies:1}]

That should beconverted into an array of 4 'Card' Objects:

[{ id: 1, copyVersion:1},
    { id: 1, copyVersion:2}.
    { id: 1, copyVersion:3},
     { id: 2, copyVersion:1}]

I appreciate any insight!

Edit 1

Tried the following:

this.posts.subscribe((posts) => {
  posts.forEach( post => {
    console.log(post);
    this.cardsList.push(post);
  });
});

But get:

core.js:1350 ERROR TypeError: Cannot read property 'push' of undefined at eval (deck-list.component.ts:40)

Final Updated Code:

  static fromMultiple(multipleCard: MultipleCard): Card[] {
    const data: Card[] = [];
    for (let i = 0; i < multipleCard.copies; i++) {
      data.push(new Card(multipleCard));
    }
  return data;

}

this.postsCol = this.db.collection('cards');
this.posts = this.postsCol.valueChanges();

this.posts.subscribe((posts) => {
  posts.forEach( post => {
    const temp = Card.fromMultiple(post);
    temp.forEach(tempCard => {
      this.cardsList.push(tempCard);
    });
  });
});

You can use valueChanges() or snapshotChanges() on the collection to return the Observable from your request.

Here is an example of valueChanges() :

this.posts = this.db.collection<MultipleCard[]>('posts').valueChanges();

so this line returns an Observable<MultipleCard[]> which you can then subscribe to and receive the MultipeCard[] array, like so:

this.posts.subscribe((posts) => {
   console.log(posts); //This is the array of posts, not an observable
 });

You do not need to manually subscribe to this in your component as thats what the ASYNC pipe does for you in the markup. You can set your forLoop in your markup like so *ngFor="let post of (posts | async)" and that will also begin the subscription to your Observable data and also close the subscription when this component is destroyed. I hope this can be of help!

You should do some more research on Observable data and the rxjs library that this is utilizing as it will give you more insight on the data you are handling from firebase (specifically firestore).

You'd either subscribe to your observable stream or promisify it and see what are you getting back. Say a function getData() returns an observable, you can either do

getData().subscribe((card: any) => * do something *) 

or

getData().toPromise().then((card: any) => * do something*)  

I'd suggest doing this and logging in the response (card here). That way you'll have an idea what's happening.

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