3

I'm using AngularFire2, trying to get lists out of lists. A nested *ngFor within an *ngFor doesn't show on the view...

app.componnent

...
constructor(private _af: AngularFire) {
    this.lists = this._af.database.list(this._API_URL);
}
...

app.component.html

<div *ngFor="let list of lists | async">
    {{sublist.name}}<br/> <!-- I can see you -->

    <!--******* I can't see you **********-->
    <div *ngFor="let rootword of list.rootwords">
        {{rootword.word}} {{rootword.total}}
    </div> 
</div>

Example of Firebase

maindb
  |_list1
  |  |_name: 'List 1"
  |  |_rootwords
  |     |_apple
  |     |   |_word: 'apple'
  |     |   |_total: 4
  |     |
  |     |_banana
  |     |   |_word: 'banana'
  |     |   |_total: 2
  |     |_carpet 
  |     |   |_word: 'carpet'
  |     |   |_total: 21
  |
  |_list2
     |_name: "List 2"
     |_rootwords
        |_elephant
        |    |_word: 'elephant'
        |    |_total: 4
        |_sloth
             |_word: 'sloth
             |_total: 5

How do you nest an ngFor in an ngFor with firebase.list ?? Do I need to map or filter? Does AngularFire2 have a way to convert the inner object to an array?

All suggestions appreciated!

1 Answer 1

2

You can replace the rootwords object with an array using the map opererator and Array.prototype.reduce, like this:

import 'rxjs/add/operator/map';

constructor(private _af: AngularFire) {

  this.lists = this._af.database
    .list(this._API_URL)

    // Use map the map operator to replace each item in the list:

    .map(list => list.map(item => ({

      // Map to a new item with all of the item's properties:
      ...item,

      // And replace the rootwords with an array:
      rootwords: Object.keys(item.rootwords)

        // Use reduce to build an array of values:
        .reduce((acc, key) => [...acc, item.rootwords[key]], [])
      })
    ));
}

Or, without the spread syntax:

import 'rxjs/add/operator/map';

constructor(private _af: AngularFire) {

  this.lists = this._af.database
    .list(this._API_URL)
    .map(list => list.map(item => {
        var copy = Object.assign({}, item);
        copy.rootwords = Object.keys(item.rootwords).reduce((acc, key) => {
            acc.push(item.rootwords[key]);
            return acc;
        }, []);
        return copy;
    }));
}
Sign up to request clarification or add additional context in comments.

7 Comments

Didn't work... starting at ...item, getting an error Property Assignment expected.. Do I have to import another rxjs to use this syntax? But commenting that out, still get error: ViewWrappedError Error: Error in ./LearnComponent class LearnComponent - inline template:19:17 caused by: Invalid argument '[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],...' for pipe 'AsyncPipe' at ViewWrappedError.ZoneAwareError (localhost:4200/polyfills.bundle.js:1150:33) at ViewWrappedError.BaseError [as constructor] ...
Commented out second | async, now Error - Property assignment expected. caused still by ...item
What version of TypeScript are you using?
TypeScript v2.1.1
If I manually add the item keys, it works and remove the inner | async pipe.
|

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.