1

I want to be able to do run an *ngFor on the users property of the groups object in my Firebase database.

So far, I'm trying this:

<h5>{{ (group$ | async)?.name }}</h5>
<div class="gd-users-container">
  <span *ngFor="let user of (group$ | async)?.users">{{ user.email }}</span>
</div>

Where group$ = getGroup(): FirebaseObjectObservable<any>;

And the data's structure looks like this:

"groups": {
  "marketing": {
    "apps": {
      "someid": {
        "id": "someid",
        "name": "Payroll"
      }
    },
   "id": "marketing",
   "name": "Marketing",
   "users": {
     "23948n": {
       "id": "23948n",
       "email": "[email protected]"
      },
     "asdfasdfasdf": {
       "id": "asdfasdfasdf",
       "email": "[email protected]"
      }
    }
  }
}

When I try the markup above, I get the name of the group back, but I get an error when it comes to the *ngFor:

ERROR Error: Cannot find a differ supporting object '[object Object]'
of type 'object'. NgFor only supports binding to Iterables such as Arrays.

It makes sense to me why I am receiving that error, because the property users on the group object is not an array, but rather an object. My question is how to get it so that the users property can be treated as an array.

2 Answers 2

2

You don't need the async pipe in this context. As the error states, *ngFor can only bind to iterables, but what the async pipe does is:

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted

So you don't get an iterable. Instead, use:

*ngFor="let email of emails"

EDIT: No, it won't convert it an array. As above, it takes an iterable, so you need to do that yourself, with, say:

let emails: [];
Object.keys(group$?.users).map(key => emails.push(group$?.users[key].email)))

Add additional properties, or the whole user object, to the array, as you wish. For exaxmple, in ES7's Object.values():

let users = Object.values(group$.users)

And the original <div *ngFor = "let user of users">{{user?.email}}</div>

Sign up to request clarification or add additional context in comments.

4 Comments

Okay, so that gets rid of the error, but it still doesn't convert that property to an array to iterate through its objects. How can I achieve that?
@JoshuaKemmerer See edit: Angular won't mangle your data structure, you need to modify it for yourself.
@JoshuaKemmerer I appreciate you accepting my answer, but do feel free to post a new answer with the content of your edit. It's perfectly acceptable. I'll leave the edit pending until you do, then reject it (it belongs in a new answer). :)
Thanks, that looks better to me!
0

Response from Joshua:

So, what I ended up doing was subscribing to the group object and created a separate users$ model that was assigned to group.users:

this.group$ = this.route.paramMap
  .switchMap((params: ParamMap) =>
    this.gs.getObjectObservable(params.get('id')));

this.group$.subscribe(snapshot => {
  this.users$ = Object.values(snapshot.users);
});

Then I just displayed the data as:

<div *ngFor="let user of users$">
  {{ user.email }}
</div>

Not sure if this is the best way to do it, but it seems the easiest. Also, from what I understand of subscriptions and "snapshots", this should work out fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.