NikeBless
NikeBless

Reputation: 101

*ngIf doesn't delete the element when False, creates new one when True

I am just starting with Angular and have a problem with *ngIf

When the app starts, *ngIf="item.done" correctly displays (or not displays) the element based on whether the ToDo item is done. However, when I click on the element, the done state changes (I am console.logging it), but the element doesn't disappear, whatever the state. Instead, when the state goes back to done, it creates the same element again.

My HTML template

The onTick() function that changes the item.done state

  1. item.done = false Hidden Screenshot
  2. 1st click –> item.done = true Shown
  3. 2nd click –> item.done = false Shown
  4. 3rd click –> item.done = true Shown TWICE Screenshot

// MOCK DATA

import { Item } from './item';

export const ITEMS: Item[] = [
  {id: 1, title: 'Buy Milk', done: false},
  {id: 2, title: 'Do Math', done: true},
  {id: 3, title: 'Cook food', done: false}
]



// THE COMPONENT TypeScript

import { Component, OnInit } from '@angular/core';
import { ITEMS } from './mock-items';
import { Item } from './item';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {
  items: Item[] = [];

  constructor() {
    this.items = ITEMS
  }

  ngOnInit() {
  }

  onTick(item) {
    console.log('Item was: ', item.done)
    item.done = !item.done
    console.log('Item became: ', item.done)

  }

}
<!-- THE COMPONENT HTML -->
<div class="list">
  <div class="list--header">
    <h1>List</h1>
  </div>

  <div class="list--content">
    <ul class="list--items">
      <li *ngFor="let item of items">
        <div class="checkbox" (click)="onTick(item)">
          <input type="checkbox" style="display: none">
          <i *ngIf="item.done" class="tick fas fa-check"></i>
        </div>
        {{item.title}}
      </li>
    </ul>
  </div>

  <div class="list--footer">

  </div>
</div>

Upvotes: 7

Views: 6986

Answers (3)

Daniel B
Daniel B

Reputation: 8879

Adding to the list of suggested answers.

You can set the FontAwesomeConfig property autoReplaceSvg to nest, which will automatically nest the SVG inside the <i> element instead, and thus not mess up the HTML.

<script>
  // Add in your index.html or similar
  FontAwesomeConfig = { autoReplaceSvg: 'nest' }
</script>

And use it like normal

<i class="my-icon fas fa-coffee" data-fa-mask="fas fa-circle"></i>

and you'll get the following result

<i class="my-icon" data-fa-mask="fas fa-circle" data-fa-processed="">
  <svg class="svg-inline--fa fa-coffee fa-w-16" data-fa-mask="fas fa-circle" aria-hidden="true" data-fa-processed="" data-prefix="fas" data-icon="coffee" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">...</svg>
</i>

Check out the documentation for further reference.

Upvotes: 1

NikeBless
NikeBless

Reputation: 101

EDIT

The problem happens when Font Awesome's SVG, instead of appearing as a child of the <i *ngIf="item.done" class="tick fas fa-check"></i>, replaces the element, and so the *ngIf attribute disappears. Looks like we shouldn't ever use Angular attributes on an element with Font Awesome classes (target the parent element, instead).

How it Used to Be (Doesn't work)

<i *ngIf="item.done" class="tick fas fa-check"></i>

Solution

<div *ngIf="item.done">
   <i class="tick fas fa-check"></i>
</div>

Upvotes: 3

iHazCode
iHazCode

Reputation: 771

Try wrapping the icon in a DIV... Also it is important to note that ngIf isn't intended to "hide" elements. It will in fact add and remove them from the DOM. If your intent is to hide/show, you should take a look at ngHide.

Hope this helps.

Upvotes: 2

Related Questions