0

I want to have a filter based on active-states from available checkboxes.

First everything should gets displayed, after a filter is selected, in this case a selection of hero names should only display heroes which contains atleast the name.

The interesting part is that: If I try to change the value back to the "full"-object it is not taking the complete object but an altered version of that.

I do not know what is happening there. Because I only initialized the full-object in the constructor of the app. With full-object I mean fullHeroes.

App.Component.ts :

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

interface Hero {
    name: string;
}

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent {
  readonly fullHeroes: Hero[] = [];
  heroes: Hero[] = [];

  constructor() {
    this.heroes.push(
        { name: 'Bob' }, { name: 'Alice' }, { name: 'Mallory' }
    );
    this.fullHeroes = this.heroes.slice(0);
}

filter(name, checked) {
    if (checked) {
        for (let i = 0; i <= this.heroes.length; i++) {
            let found = false;
            const currentHero = this.heroes[i];
            if (currentHero && currentHero.name === name) {
                found = true;
            }
            if (found) {
                this.heroes.splice(i, 1);
            }
        }
    } else {
        this.heroes = [];
        this.heroes = this.fullHeroes;
    }
    return;
  }
}

App.component.html :

   <div class="container">
    <h1>World of Heroes</h1>
    <p>Filter your Heroes based on names!</p>

    <div class="filter">
      <form #heroForm="ngForm">

        <fieldset>
          <legend>Choose the names</legend>
          <div class="form-check" *ngFor="let hero of heroes">
            <label class="form-check-label">
                <input  class="form-check-input" type="checkbox" [name]="hero.name" (change)="filter($event.target.name, $event.target.checked)"> {{hero.name}}
            </label>
          </div>
        </fieldset>

      </form>
    </div>

    <hr>
  <h2>Results:</h2>

    <div class="row result-list">
      <div class="col-md-4 hero" *ngFor="let hero of heroes">
        <h3>Name: {{hero.name}}</h3>
      </div>
    </div>
  </div>
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
MadScientisto
  • 169
  • 2
  • 13
  • Possible duplicate of [Setting one object equal to another object with the assignment operator in Javascript](https://stackoverflow.com/questions/1948809/setting-one-object-equal-to-another-object-with-the-assignment-operator-in-javas) – Dexygen Dec 25 '17 at 22:09

3 Answers3

2

If you want to make a clone for the array this.fullHeroes into the array this.heroes, use:

this.heroes = JSON.parse(JSON.stringify(this.fullHeroes));

This way you will do a full copy of the array this.fullHeroes into this.heroes one, and then changes in this.heroes will not affect the other array.

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
  • Thank you very much this solved my first problem. However it seems like just using this.heroes = JSON.parse(JSON.stringify(this.fullHeroes)); doesn't solve my logical problem with getting the correct results based on the selected checkboxes. – MadScientisto Dec 25 '17 at 17:50
  • this is an answer for `Angular cloned array gets changed automatically` if it helped you then accept the answer that it can help other peoples. For the other problem you have, you can ask a new more specific question for that, that way you can get more help. – HDJEMAI Dec 25 '17 at 17:53
0
this.heroes = this.fullHeroes

After you execute that line, every time you mutate heroes, you also mutate fullHeroes, since they both refer to the same array. You need to make a copy of fullHeroes.

Note that you're abusing map() where you should be using forEach(). And you're using a loop where you could use some().

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thank you for the answer. I'm using forEach instead of map and using slice to create a real copy of the fullHeroes. However that doesn't solve my logical problem with displaying the correct result based on the selected checkboxes. Is there a simpler alternative way to get that thing done? – MadScientisto Dec 25 '17 at 17:52
0

You can use the TypeScript spread operator to clone the array:

const a1 = [1, 2, 3, 4, 5, 6];
const a2 = [...a1];
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
JayChase
  • 11,174
  • 2
  • 43
  • 52