Kevin Rovers
Kevin Rovers

Reputation: 97

Angular: How to reset child components

I have written a Java backend that is used as my server and will serve all data. The frontend is an Angular 8 application.

I've created a stripped version of my frontend application in stackblitz: https://stackblitz.com/edit/angular-code-game

The game consists of 1 parent component (GAME) and 4 (the same) child components (COUNTER). When I start a new (instance of the) game, I want the counters to be set to their initial state.

I have done some research, and I think I should use @ViewChild, but I don't know how I can get to reset my 4 child components in my parent component file.

To illustrate my problem:

There should be some logic inside the app.component.ts:

Anyone who knows how to fix this?

Upvotes: 3

Views: 21032

Answers (2)

bryan60
bryan60

Reputation: 29335

since you have multiple, you probably want ViewChildren... suppose your child components have some reset() method on them that puts them to their initial state, do this:

in parent:

@ViewChildren(CounterComponent)
childGames: QueryList<CounterComponent>

resetAll() {
  this.childGames.forEach(c => c.reset()); // or whatever you want to do to it here
}

call resetAll() as needed.

here is a sample blitz: https://stackblitz.com/edit/angular-code-game-aq7y5g?file=src/app/app.component.ts

Upvotes: 12

StephenHealey86
StephenHealey86

Reputation: 81

Create a method in your child class that does the resetting of the child, then you can call it in your parent view. Add a reference to the child then use it in the (click) event to call its own method.

<div class="pageBox">
  <div class="top">
    <div class="title">Vaultcracker</div>

    <div>
      <div class="gameButtons">
        <!-- When starting a new game, the counters should be all green again. -->
        <div (click)="child1.initialise(); child2.initialise(); child3.initialise(); child4.initialise()">Start a new game</div>
        <div (click)="getClue()">Get a new clue</div>
      </div>
      <p *ngIf="result">{{result.message}}</p>

      <div class="counters">
        <app-counter #child1 name="A" (counterResult)="checkCounter('A', $event)"></app-counter>
        <app-counter #child2 name="B" (counterResult)="checkCounter('B', $event)"></app-counter>
        <app-counter #child3 name="C" (counterResult)="checkCounter('C', $event)"></app-counter>
        <app-counter #child4 name="D" (counterResult)="checkCounter('D', $event)"></app-counter>
      </div>

      <ul class="clues" *ngIf="clues">
        <li *ngFor="let clue of clues">
          <!-- Clues are dummies -->
          <p>{{ clue }}</p>
        </li>
      </ul>
    </div>
  </div>
  <div class="bottom">
    <div class="safe">
      <div class="case"></div>
      <div class="code">
        <span>{{ code.A }}</span>
        <span>{{ code.B }}</span>
        <span>{{ code.C }}</span>
        <span>{{ code.D }}</span>
      </div>
      <div class="lock" (click)="openVault()">OPEN</div>
    </div>
  </div>
</div>

import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';

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

  @Input() name;
  @Output() counterResult = new EventEmitter<string>();
  counter = {};

  constructor() {
  }

  ngOnInit() {
    this.initialise();
  }

  initialise() {
    this.counter = {
    0: 'on',
    1: 'on',
    2: 'on',
    3: 'on',
    4: 'on',
    5: 'on',
    6: 'on'
  };
  }

  click(i) {
    this.counter[i] = this.counter[i] === 'on' ? 'off' : 'on';
    Object.values(this.counter);

    if (this.filterByValue()) {
      this.counterResult.emit(Object.values(this.counter).indexOf('on').toString());
    }
  }

  filterByValue() {
    return Object.values(this.counter).filter(data => data === 'on').length === 1;
  }

}

Upvotes: 0

Related Questions