Rasmus Lave Schulz
Rasmus Lave Schulz

Reputation: 51

use *ngFor on nested JSON array

I am trying to use an expansion panel to hold my data from database so that I can list the data more nicely.

I'm trying to print out my nested JSON array with an *ngFor. Problem is my JSON is nested, how will i manage to do this?

Here I am trying to print out my name and total sales in the top of the panel. After it is clicked it should then open the underpanel with my other data from the nested array.

HTML

<mat-accordion>
    <mat-expansion-panel *ngFor="let data of dataList">
        <mat-expansion-panel-header>
            <mat-panel-title>
                {{data.name}}
            </mat-panel-title>
        <mat-panel-description>
            {{data.total_sales}}
        </mat-panel-description>
    </mat-expansion-panel-header>
        {{data.sales}}
    </mat-expansion-panel>
</mat-accordion>

JSON return by my get.http function

{""
    :{"name":null,
    "total_sales":1200,
    "sales": [
    {
         "name":null,
         "masterID":"5049",
         "beerline":"2",
         "containerNo":"1",
         "pluNo":"1",
         "pluName":"Smirnoff 2cl",
         "pluDepartment":"VODKA",
         "pluPrice":"20.00",
         "sold_count":"54"
    }, 
    {
         "name":null,
         "masterID":"4028",
         "beerline":"8",
         "containerNo":"4",
         "pluNo":"1",
         "pluName":"Smirnoff 2cl",
         "pluDepartment":"VODKA",
         "pluPrice":"20.00",
         "sold_count":"1"
    },
    {
         "name":null,
         "masterID":"4028",
         "beerline":"9",
         "containerNo":"5",
         "pluNo":"3",
         "pluName":"Johnsrom",
         "pluDepartment":"rom",
         "pluPrice":"25.00",
         "sold_count":"1"
    },
    {
         "name":null,
         "masterID":"4028",
         "beerline":"10",
         "containerNo":"6",
         "pluNo":"3",
         "pluName":"Johnsrom",
         "pluDepartment":"rom",
         "pluPrice":"25.00",
         "sold_count":"1"
    },
    {
         "name":null,
         "masterID":"4028",
         "beerline":"11",
         "containerNo":"7",
         "pluNo":"3",
         "pluName":"Johnsrom",
         "pluDepartment":"rom",
         "pluPrice":"25.00",
         "sold_count":"1"
    },
    {
         "name":null,
         "masterID":"4028",
         "beerline":"12",
         "containerNo":"8",
         "pluNo":"3",
         "pluName":"Johnsrom",
         "pluDepartment":"rom",
         "pluPrice":"25.00",
         "sold_count":"1"
    }
    ]},
         "Show Room":
    {
         "name":"Show Room",
         "total_sales":4110,

 "sales":[
           {
            "name":"ShowRoom",
            "masterID":"4028",
            "beerline":"1",
            "containerNo":"1",
            "pluNo":"1",
            "pluName":"Smirnoff2cl",
            "pluDepartment":"VODKA",
            "pluPrice":"20.00",
            "sold_count":"198"
           },
           {
            "name":"ShowRoom",
            "masterID":"4028",
            "beerline":"1",
            "containerNo":"2",
            "pluNo":"3",
            "pluName":"Johnsrom",
            "pluDepartment":"rom",
            "pluPrice":"25.00",
            "sold_count":"5"
           },
           {
            "name":"ShowRoom",
            "masterID":"4028",
            "beerline":"3",
            "containerNo":"2",
            "pluNo":"3",
            "pluName":"Johnsrom",
            "pluDepartment":"rom",
            "pluPrice":"25.00",
            "sold_count":"1"
           }
           ]},
           "Henriks Place":
           {
           "name":"Henriks Place",
           "total_sales":50,
              "sales":
                      [
                        {
                         "name":"Henriks Place",
                         "masterID":"4028",
                         "beerline":"4",
                         "containerNo":"2",
                         "pluNo":"3",
                         "pluName":"Johnsrom",
                         "pluDepartment":"rom",
                         "pluPrice":"25.00",
                         "sold_count":"1"
                        },
                        {
                         "name":"Henriks Place",
                         "masterID":"4028",
                         "beerline":"6",
                         "containerNo":"3",
                         "pluNo":"3",
                         "pluName":"Johnsrom",
                         "pluDepartment":"rom",
                         "pluPrice":"25.00",
                         "sold_count":"1"
            }
        ]
     }
}

EDIT: ERROR I GET:

ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
    at NgForOf.push../node_modules/@angular/common/fesm5/common.js.NgForOf.ngDoCheck (common.js:3152)
    at checkAndUpdateDirectiveInline (core.js:9253)
    at checkAndUpdateNodeInline (core.js:10514)
    at checkAndUpdateNode (core.js:10476)
    at debugCheckAndUpdateNode (core.js:11109)
    at debugCheckDirectivesFn (core.js:11069)
    at Object.eval [as updateDirectives] (SaleComponent.html:33)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:11061)
    at checkAndUpdateView (core.js:10458)
    at callViewAction (core.js:10699)

function returning json:

getSale1(): Observable<Sale1Model[]> {
        return this.http.get<Sale1Model[]>(API_URL + '/live/sale', this.httpUtils.getHTTPHeader())

    }

EDIT 2:

This is my model class:

export class Sale1Model {

    constructor(
        public name: string,
        public total_sales: string,
        public sales: string[]) { }

Upvotes: 2

Views: 1200

Answers (2)

Maycon Teixeira
Maycon Teixeira

Reputation: 21

use another *ngFor on panel body to iterate nested array

<mat-accordion>
    <mat-expansion-panel *ngFor="let data of dataList">
        <mat-expansion-panel-header>
            <mat-panel-title>
                {{data.name}}
            </mat-panel-title>
        <mat-panel-description>
            {{data.total_sales}}
        </mat-panel-description>
    </mat-expansion-panel-header>
        <div class="sale-body" *ngFor="let s of data.sales"> <sale body here> </div>
    </mat-expansion-panel>
</mat-accordion>

Upvotes: 1

Artyom Amiryan
Artyom Amiryan

Reputation: 2966

just add one more *ngFor loop for nested sales array

<mat-accordion>
    <mat-expansion-panel *ngFor="let data of dataList">
        <mat-expansion-panel-header>
            <mat-panel-title>
                {{data.name}}
            </mat-panel-title>
        <mat-panel-description>
            {{data.total_sales}}
        </mat-panel-description>
    </mat-expansion-panel-header>
        <div *ngFor="let sale of data.sales">{{sale.name}}</div> // use your sale object here as you want
    </mat-expansion-panel>
</mat-accordion>

Upvotes: 0

Related Questions