1

I am new to Angular 4 and I am stuck in an issue in my code. Below is my code:

JSON:

          [{"name": "A", "date": "2017-01-01", "value": "103.57"},
           {"name": "A", "date": "2017-01-08", "value": "132.17"}, 
           {"name": "A", "date": "2017-01-15", "value": "268.04"}, 
           {"name": "A", "date": "2017-01-22", "value": "235.10"}, 
           {"name": "A", "date": "2017-01-29", "value": "83.78"}, 
           {"name": "A", "date": "2017-02-12", "value": "162.52"}, 
           {"name": "A", "date": "2017-02-19", "value": "131.63"}, 
           {"name": "B", "date": "2017-01-01", "value": "0.56"}, 
           {"name": "B", "date": "2017-01-08", "value": "275.55"}, 
           {"name": "B", "date": "2017-01-15", "value": "288.37"}, 
           {"name": "B", "date": "2017-01-29", "value": "250.05"}, 
           {"name": "B", "date": "2017-02-05", "value": "124.90"}, 
           {"name": "B", "date": "2017-02-12", "value": "6.15"}, 
           {"name": "C", "date": "2017-01-08", "value": "75.55"}, 
           {"name": "C", "date": "2017-01-15", "value": "88.37"}, 
           {"name": "C", "date": "2017-01-22", "value": "34.31"}, 
           {"name": "C", "date": "2017-01-29", "value": "0.05"}, 
           {"name": "C", "date": "2017-02-05", "value": "4.90"}, 
           {"name": "C", "date": "2017-02-12", "value": "6.15"}, 
           {"name": "D", "date": "2017-01-08", "value": "5.55"}, 
           {"name": "D", "date": "2017-01-15", "value": "8.37"}, 
           {"name": "D", "date": "2017-01-22", "value": "4.31"}, 
           {"name": "D", "date": "2017-01-29", "value": "50.05"}, 
           {"name": "D", "date": "2017-02-05", "value": "4.90"}, 
           {"name": "D", "date": "2017-02-12", "value": "6.15"}

HTML:

                        <thead>

                            <tr id="row">

                                <th class="align-right"  *ngFor="let item of calendarTableSelected|slice:0:8">{{item.date}}</th>
                            </tr>

                        </thead>

                        <tbody id="body">

                            <tbody contenteditable='true'>

                            <tr  class="align-right">
                                <ng-container *ngFor="let item of calendarTableSelected">
                                    <td *ngIf="item.name == 'A'" [(ngModel)]="item.value" ngDefaultControl>  
                                           {{item.value}}
                                </td>
                                </ng-container>
                            </tr>
                            <tr  class="align-right">
                                    <ng-container *ngFor="let item of calendarTableSelected">
                                        <td *ngIf="item.name == 'B'" [(ngModel)]="item.value" ngDefaultControl>  
                                                {{item.value}}
                                    </td>
                                    </ng-container>
                            </tr>
                            <tr  class="align-right">
                                    <ng-container *ngFor="let item of calendarTableSelected">
                                        <td *ngIf="item.name == 'C'" [(ngModel)]="item.value" ngDefaultControl>  
                                                {{item.value}}
                                    </td>
                                    </ng-container>
                            </tr>
                              <tr  class="align-right">
                                    <ng-container *ngFor="let item of calendarTableSelected">
                                        <td *ngIf="item.name == 'D'" [(ngModel)]="item.value" ngDefaultControl>  
                                                {{item.value}}
                                    </td>
                                    </ng-container>
                            </tr>

                        </tbody>
                    </table>

                </div>

I do not want to hard-code the names: "A", "B", "C" and "D" in ngIf in HTML for the values to be displayed. Instead I want it to loop in the "name" field and display the value accordingly for that particular name.
I also do not want to change the json structure.

Please help.

Regards Neha

Neha Uniyal
  • 185
  • 1
  • 3
  • 14

2 Answers2

0

Edit:

More efficient (only iterate the whole array once and then iterate just for each specific name rather then the whole array for each name):

In the html:

<ng-container *ngFor="let name of names">
      <tr class="align-right">
        <ng-container *ngFor="let item of seperated[name]">
          <td [(ngModel)]="item.value" ngDefaultControl>
            {{item.value}}
          </td>
        </ng-container>
      </tr>
</ng-container>

In the Component:

  ngOnInit() {
    this.initNames();
  }


  seperated = {};

  names = [];

  initNames() {
    this.calendarTableSelected.forEach(item => {
      if (!this.seperated[item.name]) {
        this.seperated[item.name] = [];
      }

      this.seperated[item.name].push(item);
    });

    this.names = Object.keys(this.seperated);
  }

This is probably not be the most efficient way to do it, but you can try save in another array only the items by distinct name (every name can only appear once) , then do something like this

      <tr class="align-right" *ngFor="let unique of distinctNames">
        <ng-container *ngFor="let item of calendarTableSelected">
          <td *ngIf="item.name == unique.name" [(ngModel)]="item.value" ngDefaultControl>
            {{item.value}}
          </td>
        </ng-container>
      </tr>

In the component :

  ngOnInit() {
    this.initNames();
  }

  distinctNames = [];

  initNames() {
    let unique = this.calendarTableSelected.filter(this.onlyUnique);
    this.distinctNames = unique;
  }

  onlyUnique(item, index, arr) {
    return arr.indexOf(arr.find(v => v.name == item.name)) === index;
  }
Ofek Amram
  • 452
  • 2
  • 6
0

Given your data is returned and stored in the variable data.

First, create a variable called names :

names: string[] = [];

Then, on data received, populate your array :

this.names = this.data.filter(line => {
  if (!this.names.includes(line.name)) { this.names.push(line.name); }
});

In your HTML, you can now iterate over your array of names

<tr class="align-right" *ngFor="let name of names">
  <ng-container *ngFor="let item of calendarTableSelected">
    <td *ngIf="item.name == name" [(ngModel)]="item.value" ngDefaultControl>
      {{item.value}}
    </td>
  </ng-container>
</tr>