Angular 2 Mostrar e ocultar um elemento

174

Estou tendo um problema ao ocultar e mostrar um elemento dependendo de uma variável booleana no Angular 2.

este é o código para a div mostrar e ocultar:

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

a variável é "editada" e é armazenada no meu componente:

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);
  }
}

O elemento está oculto, quando a função saveTodos é iniciada, o elemento é mostrado, mas após 3 segundos, mesmo que a variável volte a ser falsa, o elemento não se oculta. Por quê?


fonte

Respostas:

167

Você deve usar a diretiva * 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);
  }
}

Atualização: está faltando a referência ao escopo externo quando você está dentro do retorno de chamada de tempo limite.

então adicione o .bind (this) como adicionei acima

Q: editado é uma variável global. Qual seria sua abordagem dentro de um loop * ngFor? - Blauhirn

R: Eu adicionaria editar como uma propriedade ao objeto sobre o qual estou iterando.

<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);
  }
}
inoabriano
fonte
editedé uma variável global. Qual seria sua abordagem dentro de um *ngFor-loop?
precisa saber é
Editado não seria uma variável global, ela pertence ao componente. Vou adicionar a resposta acima.
inoabrian
como acessar o timer globalmente do serviço?
Kumaresan Perumal
1
Se alguns componentes angulares do material falharem ao inicializar e funcionarem corretamente, como mat-paginator. Acho que usar [oculto] é a melhor opção para alguns casos.
AmirHossein Rezaei
186

Existem duas opções, dependendo do que você deseja alcançar:

  1. Você pode usar a diretiva oculta para mostrar ou ocultar um elemento

    <div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
      <strong>List Saved!</strong> Your changes has been saved.
    </div>
  2. Você pode usar a diretiva de controle ngIf para adicionar ou remover o elemento. Isso é diferente da diretiva oculta porque não mostra / oculta o elemento, mas adiciona / remove do DOM. Você pode perder dados não salvos do elemento. Pode ser a melhor opção para um componente de edição que é cancelado.

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

Para seu problema de alteração após 3 segundos, pode ser devido à incompatibilidade com setTimeout. Você incluiu a biblioteca angular2-polyfills.js na sua página?

gentiane
fonte
5
[hidden]="edited"parece não ter nenhum efeito ...?
precisa saber é
5
Caso tenha problemas com o oculto, siga a resposta de stackoverflow.com/a/35578093/873282 : [hidden] { display: none !important;}no seu css global.
Koppor #
30

Quando você não se importa com a remoção do elemento dom Html, use * ngIf.

Caso contrário, use isto:

<div [style.visibility]="(numberOfUnreadAlerts == 0) ? 'hidden' : 'visible' ">
   COUNTER: {{numberOfUnreadAlerts}} 
</div>
Dudi
fonte
14

Para o componente filho mostrar que eu estava usando *ngif="selectedState == 1"

Em vez disso, eu usei [hidden]="selectedState!=1"

Funcionou para mim .. carregar o componente filho corretamente e depois de ocultar e desassociar o componente filho não foi indefinido após o uso.

Swapnil Kale
fonte
6

Este é um bom caso de uso para uma diretiva. Algo assim é surpreendentemente útil.

@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
fonte
Gosto da ideia, mas isso removerá o elemento completamente. Eu mudei para ocultar, para que você possa reutilizá-lo, mas isso não oculta o elemento provavelmente devido ao ngIfis true. Existe uma maneira de definir a variável do pai que controla isso false?
occasl
Você não pode simplesmente adicionar uma classe oculta ou algo assim, em vez de chamar remover? Essa técnica é bastante genérica.
Aluan Haddad
Acho que o problema é ngIfmais se o elemento está no DOM ou não. O que eu quero é o seguinte: <div [hidden]="messages" [removeAfter]=3000>...onde eu mostro / oculto as mensagens, se houver alguma, e removo as mensagens após 3 segundos, para que o usuário não precise fechar a caixa. Eu adicionei sua diretiva acima e mudei para fazer um, hide()mas ela não é chamada quando as mensagens são mostradas. Como faço para que seja invocado no evento? @Output()e EventEmitter?
occasl
4

Podemos fazer isso usando o snippet de código abaixo.

Código angular:

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

Modelo 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
fonte
3

Dependendo de suas necessidades *ngIfou de [ngClass]="{hide_element: item.hidden}"onde a classe CSS hide_elementé{ display: none; }

*ngIfpode causar problemas se você estiver alterando a *ngIfremoção de variáveis ​​de estado ; nesses casos, display: none;é necessário usar CSS .

Luke Dupin
fonte
0

A solução @inoabrian acima funcionou para mim. Eu tive uma situação em que atualizava minha página e meu elemento oculto reaparecia na minha página. Aqui está o que eu fiz para resolvê-lo.

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

ngOnInit() {
      if (condition is true) {
        this.showJoinTodayBtn = true;
      } else {
        this.showJoinTodayBtn = false;
      }
}
Jason Spence
fonte
0

Basta adicionar bind (this) na sua função setTimeout, ela começará a funcionar

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

e na mudança de 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>

Para

<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
fonte