Angularfire: Question: How to grab data from two lists and combine them correctly

Created on 3 Aug 2016  路  10Comments  路  Source: angular/angularfire

I am just about to split up and refactor some of my data so I can query it a bit better however I am still struggling to combine two sets of data for display purposes, in timestamp order. I have seen it done with .map but cannot get it to work for me. Would anyone be kind enough to explain how to do it in terms of angularfire2.

database

Most helpful comment

Hey @borntodesign, this is what I do.

Suppose that you have an structure like this:

{
  projects: {
    project1: {
      members: {
        user1: {...}
      }
    } 
  },
  users: {
    user1: {...}
  }
}

So you can do:

let members = this.af.database.list('/projects/project1/members') // Primary list
  .map(items => {
    // `items` is an array of all items at the moment
    for (let item of items) {
      // Find each corresponding associated object and store it as a FibreaseObjectObservable
      item.user = this.af.database.object(`/users/${item.$key}`);
    }

    return items;
  });

I like to abstract that map code to a function that I share across my project.

I hope it helps :)

All 10 comments

Hey @borntodesign, this is what I do.

Suppose that you have an structure like this:

{
  projects: {
    project1: {
      members: {
        user1: {...}
      }
    } 
  },
  users: {
    user1: {...}
  }
}

So you can do:

let members = this.af.database.list('/projects/project1/members') // Primary list
  .map(items => {
    // `items` is an array of all items at the moment
    for (let item of items) {
      // Find each corresponding associated object and store it as a FibreaseObjectObservable
      item.user = this.af.database.object(`/users/${item.$key}`);
    }

    return items;
  });

I like to abstract that map code to a function that I share across my project.

I hope it helps :)

@aguzubiaga I tried following your approach. And, here is what I did:

In my service:

getbyid (id:string): Observable<any> {
    let theme = this.af.database.object(`themes/${id}`);
    return theme.map((items) => {
          for (let i = 0; i < items.menu.length; i++) {
            items.menu[i] = this.af.database.object(`foods/${items.menu[i]}`);
          }

          return items;
      });

  }

and in my controller:

this.route.params.subscribe(params => {
      this.params = params;
      this.themeDetail = this._themes.getbyid(this.params.id);
    })

    this.themeDetail
      .subscribe((d) => { console.log(d) });

I get proper response in console. But my view is not updating.

This is how I've set up my view:

<h2 class="kc-heading-title">{{themeDetail.name | async}}</h2>
<div class="col-xs-12 col-sm-6 col-md-3" *ngFor="let food of menu | async">
  <h4 class="food-box-list-title">{{food.name}}</h4>                 
</div> 

And, I'm getting this in console response:
screen shot 2016-08-05 at 11 53 02 am

Thanks,

@dowsanjack don't you have to subscribe to each menu as well? Maybe...
@aguzubiaga my problem (more of an annoyance) is as follows:

I have a huge list of articles which all have a type: text, video, comment and image. I would like to split them up into the following:

  • articles/image
  • articles/video
  • articles/comment
  • articles/text

I still need need to list them all together in timestamp order, but this means I can run more efficient queries for example getting a text article with the name "Nice article". I have seen a couple of videos using map to nicely combine a list but have not yet got anything to work.

Kind regards :)

@aguzubiaga I find it easier rather than messing about with combining in your situation to make a food component and pass in the menu as an input, then grab it from angular in that component. Just my preference.

@dowsanjack remember that your menu array items are now observables so you should access them like this:

<h4 class="food-box-list-title">{{ (food | async)?.name }}</h4>                 

@borntodesign I understand, you can create an index of your items:

{
  articles: {
    image: {
     article1: { ... }
    }
  },
  articlesIndex: {
    article1: 'image'
  }
}

Does that work for you? I don't know if it's the best way to do it, you may want to #AskFirebase.

@aguzubiaga Thanks man. It worked.

@aguzubiaga cheers I will #AskFirebase, this bit "(food | async)?.name" is really handy though.

@bogacg please submit your own issue instead of diluting an existing discussion. It's great to link to this issue number if you think they are similar.

@aguzubiaga but how we can to access to object to display informations of user in html file like :
{{ projects.user.username }}
??

Was this page helpful?
0 / 5 - 0 ratings