0

I'm making a simple helper app for one of my favorite games and learning Angular by the way. I have a component ("wing") that contains a list of buttons, that would uncover a sublist, which is represented by another sub-component. However, the way I have it now, when I click on a given "wing" button, it also uncovers the encounter sublist for every other wing as well. This is the code for my "wing" component:

wing.component.html:

<ul>
  <li *ngFor="let wing of wings">
    <button (click)="showEncounters = !showEncounters">{{ wing.getName() }}</button>
    <app-encounter
      *ngIf="showEncounters"
      [encounters]="wing.getEncounters()">
    </app-encounter>
  </li>
</ul>

wing.component.ts:

@Component({
  selector: 'app-wing',
  templateUrl: './wing.component.html',
  styleUrls: ['./wing.component.css']
})
export class WingComponent implements OnInit {

  wings = WINGS;
  showEncounters: boolean = false;

  constructor() {
  }

  ngOnInit(): void {
  }

}

wing.ts:

export class Wing {

  private readonly name : string;
  private readonly encounters: Encounter[] = [];

  constructor(name: string, encounters: Encounter[]) {
    this.name = name;
    this.encounters = encounters;
  }

  public getName() {
    return this.name;
  }

  public getEncounters() {
    return this.encounters;
  }
}

encounter.component.html:

<ul *ngFor="let encounter of encounters">
  <li>{{encounter.getName()}}</li>
</ul>

encounter.component.ts:

@Component({
  selector: 'app-encounter',
  templateUrl: './encounter.component.html',
  styleUrls: ['./encounter.component.css']
})
export class EncounterComponent implements OnInit {

  @Input() encounters!: Encounter[];

  constructor() {
  }

  ngOnInit(): void {
  }

}

encounter.ts:

export class Encounter {

  private readonly name?: string;

  constructor(name: string){
    this.name = name;
  }

  public getName() {
    return this.name;
  }

}

Visualization before clicking any button:

before

After clicking any button:

after

The issue seems to be easy to discover - when I click a button, the "showEncounters" boolean value changes for every other "wing", however I have no idea how to fix it. I was thinking about adding a "show" boolean to the wing.ts class, but I don't think it's a good idea to mix HTML DOM logic with object properties, so I abandoned this approach. What would be the correct way to show the encounters of the clicked wing only?

1
  • showEncounters should be parth of the wing class Commented Sep 15, 2021 at 18:12

1 Answer 1

1

You need to use a map of flags instead of single flag:

@Component({
  selector: 'app-wing',
  templateUrl: './wing.component.html',
  styleUrls: ['./wing.component.css']
})
export class WingComponent implements OnInit {

  wings = WINGS;
  showEncounters: { [name: string]: boolean } = {};

  constructor() {
  }

  ngOnInit(): void {
  }

}

...

<ul>
  <li *ngFor="let wing of wings">
    <button (click)="showEncounters[wing.getName()] = !showEncounters[wing.getName()]">{{ wing.getName() }}</button>
    <app-encounter
      *ngIf="showEncounters[wing.getName()]"
      [encounters]="wing.getEncounters()">
    </app-encounter>
  </li>
</ul>
Sign up to request clarification or add additional context in comments.

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.