Angular 2 Pokaż i ukryj element

174

Mam problem z ukryciem i wyświetleniem elementu zależnego od zmiennej boolowskiej w Angular 2.

to jest kod elementu div, który ma pokazywać i ukrywać:

<div *ngIf="edited==true" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>

zmienna jest „edytowana” i jest przechowywana w moim komponencie:

export class AppComponent implements OnInit{

  (...)
  public edited = false;
  (...)
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }, 3000);
  }
}

Element jest ukryty, po uruchomieniu funkcji saveTodos element jest pokazywany, ale po 3 sekundach, nawet jeśli zmienna wróci na fałsz, element się nie ukryje. Czemu?


źródło

Odpowiedzi:

167

Powinieneś użyć dyrektywy * ngIf

<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>


export class AppComponent implements OnInit{

  (...)
  public edited = false;
  (...)
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);
  }
}

Aktualizacja: brakuje odwołania do zakresu zewnętrznego, gdy znajdujesz się wewnątrz wywołania zwrotnego Timeout.

więc dodaj .bind (this), tak jak dodałem powyżej

P: edytowana jest zmienną globalną. Jakie byłoby Twoje podejście do pętli * ngFor? - Blauhirn

Odp .: Dodałbym edit jako właściwość do obiektu, nad którym iteruję.

<div *ngFor="let obj of listOfObjects" *ngIf="obj.edited" class="alert alert-success box-msg" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>


export class AppComponent implements OnInit{
   
  public listOfObjects = [
    {
       name : 'obj - 1',
       edit : false
    },
    {
       name : 'obj - 2',
       edit : false
    },
    {
       name : 'obj - 2',
       edit : false
    } 
  ];
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);
  }
}
inoabrian
źródło
editedjest zmienną globalną. Jakie byłoby Twoje podejście w ramach *ngFor-loop?
phil294
Edytowana nie byłaby zmienną globalną, należy do komponentu. Dodam odpowiedź powyżej.
inoabrian
jak uzyskać globalny dostęp do timera z serwisu?
Kumaresan Perumal
1
ngif powoduje, że niektóre komponenty materiału kątowego nie inicjują się i nie działają poprawnie, na przykład mat-paginator. Myślę, że użycie [hidden] jest lepszym wyborem w niektórych przypadkach.
AmirHossein Rezaei
186

Istnieją dwie opcje w zależności od tego, co chcesz osiągnąć:

  1. Możesz użyć dyrektywy hidden, aby pokazać lub ukryć element

    <div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
      <strong>List Saved!</strong> Your changes has been saved.
    </div>
  2. Możesz użyć dyrektywy ngIf control, aby dodać lub usunąć element. Różni się to od dyrektywy hidden, ponieważ nie pokazuje / nie ukrywa elementu, ale dodaje / usuwa z DOM. Możesz stracić niezapisane dane elementu. Może to być lepszy wybór w przypadku anulowanego komponentu edycji.

    <div *ngIf="edited" class="alert alert-success box-msg" role="alert"> 
      <strong>List Saved!</strong> Your changes has been saved.
    </div>

Dla Ciebie problem zmiany po 3 sekundach może być spowodowany niekompatybilnością z setTimeout. Czy umieściłeś na swojej stronie bibliotekę angular2-polyfills.js?

gentiane
źródło
5
[hidden]="edited"nie wydaje się mieć żadnych efektów ...?
phil294
5
W przypadku problemów z ukrywaniem, postępuj zgodnie z odpowiedzią na stackoverflow.com/a/35578093/873282 : [hidden] { display: none !important;}w swoim globalnym css.
koppor
30

Jeśli nie zależy Ci na usunięciu elementu HTML Dom, użyj * ngIf.

W przeciwnym razie użyj tego:

<div [style.visibility]="(numberOfUnreadAlerts == 0) ? 'hidden' : 'visible' ">
   COUNTER: {{numberOfUnreadAlerts}} 
</div>
Dudi
źródło
14

Aby komponent podrzędny był widoczny, używam *ngif="selectedState == 1"

Zamiast tego użyłem [hidden]="selectedState!=1"

U mnie zadziałało ... ładowanie komponentu potomnego poprawnie i po ukryciu i odznaczeniu komponentu potomnego nie było niezdefiniowane po użyciu tego.

Swapnil Kale
źródło
6

To dobry przypadek użycia dyrektywy. Coś takiego jest zaskakująco przydatne.

@Directive({selector: '[removeAfter]'}) export class RemoveAfter {
  constructor(readonly element: ElementRef<HTMLElement>) { }

  /**
   * Removes the attributed element after the specified number of milliseconds. 
   * Defaults to (1000)
   */
  @Input() removeAfter = 1000;


  ngOnInit() {
    setTimeout(() => {
      this.element.nativeElement.remove();
    }, this.removeAfter);
  }
}
Aluan Haddad
źródło
Podoba mi się ten pomysł, ale to całkowicie usunie element. Zmieniłem go, aby ukryć, więc możesz go użyć ponownie, ale to nie ukrywa elementu prawdopodobnie z powodu ngIfjest true. Czy istnieje sposób na ustawienie zmiennej nadrzędnej, która to kontroluje false?
Occasl
Nie możesz po prostu dodać ukrytej klasy lub czegoś podobnego zamiast wywoływać usuwanie? Ta technika jest dość ogólna.
Aluan Haddad,
Myślę, że problem polega ngIfbardziej na tym, czy element jest w DOM, czy nie. Chcę tego: <div [hidden]="messages" [removeAfter]=3000>...gdzie pokazuję / ukrywam wiadomości, jeśli takie są, a następnie usuwam wiadomości po 3 sekundach, aby użytkownik nie musiał zamykać okna. Dodałem twoją dyrektywę powyżej i przełączyłem ją na wykonanie a, hide()ale nie jest wywoływana, gdy wyświetlane są komunikaty. Jak sprawić, by został wywołany w wydarzeniu? @Output()i EventEmitter?
Occasl
4

Możemy to zrobić za pomocą poniższego fragmentu kodu.

Kod kątowy:

 export class AppComponent {  
    toggleShowHide: string = "visible";  
 }

Szablon HTML:

  Enter text to hide or show item in bellow: 
  <input type="text" [(ngModel)]="toggleShowHide">
  <br>
  Toggle Show/hide:
  <div [style.visibility]="toggleShowHide">   
     Final Release Angular 2!
  </div>
Rejwanul Reja
źródło
3

W zależności od Twoich potrzeb *ngIflub miejsca, w [ngClass]="{hide_element: item.hidden}"którym hide_elementznajduje się klasa CSS{ display: none; }

*ngIfmoże powodować problemy, jeśli zmieniasz stan, zmienne *ngIfsą usuwane, w takich przypadkach display: none;wymagane jest użycie CSS .

Luke Dupin
źródło
0

@inoabrian powyżej rozwiązanie zadziałało dla mnie. Znalazłem się w sytuacji, w której odświeżyłem stronę, a ukryty element ponownie pojawił się na mojej stronie. Oto, co zrobiłem, aby go rozwiązać.

export class FooterComponent implements OnInit {
public showJoinTodayBtn: boolean = null;

ngOnInit() {
      if (condition is true) {
        this.showJoinTodayBtn = true;
      } else {
        this.showJoinTodayBtn = false;
      }
}
Jason Spence
źródło
0

Po prostu dodaj bind (this) w swojej funkcji setTimeout, a zacznie działać

setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);

i zmiana HTML

<div *ngIf="edited==true" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>

Do

<div *ngIf="edited" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>
Mukesh Rawat
źródło