Claudyu
Claudyu

Reputation: 63

Acces to a table inside a table Angular

I am new to Angular, I have declared a table and inside it another table I want to have access to its data. you can find what I have done so far below

component.ts

export interface Step {
      cols: number;
      rows: number;
      text: string;
      opt1: any[];
      opt2: any[];
}
        
export class FeaturesComponent {
    stepsTwo: Step[] = [
    {text: 'Provider', cols: 1, rows: 1, opt1: [{name: 'AWS', check:false}], opt2: [{name: 'Azure', check: false}]},
    {text: 'Architecture', cols: 1, rows: 1, opt1: [{name: 'ECS', check:false }], opt2: [{name: 'Lambda', check: false}]},    
  ];
}

component.html

<mat-grid-list cols="3" rowHeight="3:3">
               <mat-grid-tile
                 *ngFor="let step of stepsTwo"
                 [colspan]="step.cols"
                 [rowspan]="step.rows"
                 [style.background]="step.color">
                 <mat-card class="feature-card">
                    <mat-card-title   >
                       {{step.text}}
                    </mat-card-title>
                    <mat-card-content >
                      <p><button mat-raised-button >{{ step.opt1.name }}</button></p>
                      <p><button mat-raised-button >{{ step.opt2.name }}</button></p>
                   </mat-card-content>
                 </mat-card>
               </mat-grid-tile>
</mat-grid-list>

so I didn't succeed to get the name.

The idea is that I want to be give the right to select one button in each card, the button gets colored the check value resets to true and saves the name in an array or anything and export it as json which, I don't know how to do. the picture below will explain better.

example_image

Upvotes: 1

Views: 82

Answers (1)

On a first look and based on your source structure which look like so : {text: 'Provider', cols: 1, rows: 1, opt1: [{name: 'AWS', check:false}], opt2: [{name: 'Azure', check: false}]} i see that opt1 and opt2 are arrays that contain single object, so the way to show the name will be opt1[0].name.

<mat-grid-list cols="3" rowHeight="3:3">
             <mat-grid-tile
             *ngFor="let step of stepsTwo; let i = index"
             [colspan]="step.cols"
             [rowspan]="step.rows"
             [style.background]="step.color">
                <mat-card class="feature-card">
                    <mat-card-title   >
                        {{step.text}}
                    </mat-card-title>
                    <mat-card-content >
                        <p><button mat-raised-button (click)="addToSelection(i, 'opt1')">{{ step.opt1[0].name }}</button></p>
                        <p><button mat-raised-button (click)="addToSelection(i, 'opt2')">{{ step.opt2[0].name }}</button></p>
                    </mat-card-content>
                </mat-card>
                </mat-grid-title>
</mat-frid-list>

export interface Step {
      cols: number;
      rows: number;
      text: string;
      opt1: any[];
      opt2: any[];
}
    
export class FeaturesComponent {
    stepsTwo: Step[] = [
    {text: 'Provider', cols: 1, rows: 1, opt1: [{name: 'AWS', check:false}], opt2: [{name: 'Azure', check: false}]},
    {text: 'Architecture', cols: 1, rows: 1, opt1: [{name: 'ECS', check:false }], opt2: [{name: 'Lambda', check: false}]},    
  ];
  
  addToSelection(stepIdx, opt){
    if(opt === 'opt1'){
        this.stepsTwo[idx]['opt1'].check = !this.stepsTwo[idx]['opt1'].check
        this.stepsTwo[idx]['opt2'].check = !this.stepsTwo[idx]['opt1'].check
    }else{
        this.stepsTwo[idx]['opt2'].check = !this.stepsTwo[idx]['opt2'].check
        this.stepsTwo[idx]['opt1'].check = !this.stepsTwo[idx]['opt2'].check
    }
  }
}

About storing the selections, the thing that you want to do is toggle the chek inside your Step items which can be achieved as seen in the example.

However, even if the example above works fine, I think that you should change your approach of solving this problem. I would suggest if possible a data structure that looks more like this:

export interface Step {
      cols: number;
      rows: number;
      text: string;
      options: any[];
}

export class FeaturesComponent {
    stepsTwo: Step[] = [
    {text: 'Provider', cols: 1, rows: 1, options: [{name: 'AWS'}, {name: 'Azure'}]},
    {text: 'Architecture', cols: 1, rows: 1, options: [{name: 'ECS'}, {name: 'Lambda'}]},    
  ];
  
  selectedProvider = null;
  selectedArchitecture = null;
  

  addToSelection(stepIdx, opt){
    if(stepIdx === 0){
    this.selectedProvider = opt;
    }else{
    this.selectedArchtecture = opt;
    }
  }
}

The reason that im suggesting this approach is because often times when we have a problem that is related to toggling stuff we end in a situations where we are toggling the wrong stiff (especially when we are toggling stuff by reference) so my recommendation is to explicitly state in a separate field which item has been selected without modifing the initial table data source.

** EDIT

In order for the second strucure to work right your template should look like this. The main difference is that we are passing to the addToSelection function reference to the option object instead of string.

<mat-grid-list cols="3" rowHeight="3:3">
             <mat-grid-tile
             *ngFor="let step of stepsTwo; let i = index"
             [colspan]="step.cols"
             [rowspan]="step.rows"
             [style.background]="step.color">
                <mat-card class="feature-card">
                    <mat-card-title   >
                        {{step.text}}
                    </mat-card-title>
                    <mat-card-content >
                        <button *ngFor"let option of options;" mat-raised-button (click)="addToSelection(i, option)">{{ option.name }}</button>
                    </mat-card-content>
                </mat-card>
                </mat-grid-title>
</mat-frid-list>

Here is live demo at StackBlitz

Upvotes: 1

Related Questions