No internet connection
  1. Home
  2. JavaScript

Componentes em Angular

Componentes

Em Angular, os componentes são blocos de construção fundamentais da aplicação. Eles encapsulam templates, lógica e estilos para controlar partes específicas da interface do usuário.

Criando um Componente

ng generate component nome-do-componente

Estrutura de um Componente

  • Template HTML: Define a estrutura da visualização do componente usando HTML com marcações específicas do Angular, que podem incluir diretivas, interpolação de dados, eventos, etc.
  • Classe TypeScript: Implementa a lógica do componente. Aqui, você define propriedades, métodos e lida com a lógica de negócios do componente.
  • Metadados (Decorator): Um decorator (@Component) é usado para fornecer metadados ao Angular, como o seletor, o arquivo do template, estilos e outras configurações específicas do componente.

Standalone component

standalone é um conceito que surgiu no angular versão 14, e na versão 17, ele se tornou padrão para novos projetos. Um componente standalone nada mais é que um componente independente, ele não precisa ser declarado em um módulo e todas as dependências que ele usa agora são inseridos no importdo próprio componente, é uma forma de deixar menos complexo o Angular removendo a necessidades de módulos. Veja como se declara um componente standalone:

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [ReactiveFormsModule, CommonModule],
  templateUrl: './login.component.html',
  styleUrl: './login.component.css',
})

Nesse exemplo, estamos importando os módulos ReactiveFormsModule e CommonModule no próprio componente.

Ciclo de Vida do Componente

Os componentes em Angular passam por um ciclo de vida que consiste em diversos estágios, permitindo que você realize ações específicas em diferentes momentos, como inicialização, atualização ou destruição do componente. Alguns dos métodos do ciclo de vida mais comuns incluem ngOnInit, ngOnChanges, ngOnDestroy, entre outros.

ngOnInit

O ngOnInit é um método da classe que é invocada assim que o componente é resolvido, é o primeiro método a ser invocado na classe e só é invocado uma vez. Geralmente ele é usado para iniciar variáveis, fazer requisições http, etc.

export class MeusComponentesComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
    // Inicializações, requisições HTTP, etc.
  }
}

ngOnChanges

O método ngOnChanges é chamado sempre que uma alteração é detectada nas propriedades de entrada (@Input) do componente. Ele recebe um objeto do tipo SimpleChanges que contém informações sobre as mudanças que ocorreram.

export class MeusComponentesComponent implements OnChanges {

  @Input() meuInput: string;

  ngOnChanges(changes: SimpleChanges): void {
    // Lógica baseada nas mudanças nas propriedades de entrada
    if (changes.meuInput) {
      console.log('Valor anterior:', changes.meuInput.previousValue);
      console.log('Valor atual:', changes.meuInput.currentValue);
    }
  }
}

ngOnDestroy

O método ngOnDestroy é chamado justo antes do componente ser destruído. Este método é utilizado para realizar ações de limpeza, como cancelar subscrições de Observables, liberar recursos ou desinscrever-se de eventos para evitar vazamentos de memória.

export class MeusComponentesComponent implements OnDestroy {
  private subscription: Subscription;

  constructor() {
    this.subscription = // Inicializa um Observable
  }

  ngOnDestroy(): void {
    // Cancela a subscrição para evitar vazamentos de memória
    this.subscription.unsubscribe();
  }
}

Comunicação entre componentes

Muitas vezes é necessário passar uma informação do componente pai para o componente filho ou vice-versa, o que permite criar componentes reutilizáveis. Isso é possível pelo uso dos decorators @Input e @Output

Input

O @Input permite passar um dado do elemento pai para o elemento filho, sendo assim, o elemento filho só pode usar esse dado mas não altera-lo, qualquer atualização desse dado pelo elemento pai reflete na sua alteração no elemento filho, que pode ser pega pelo método ngOnChange já mencionado.

Para usa-lo basta declarar uma nova variável na classe filho e decora-la com @Input() no início.

export class FilhoComponent {
	@Input() algumaPropriedade: any;
}

Output

Permite que um componente filho emita eventos para o componente pai. Isso é útil quando um componente filho precisa notificar o componente pai sobre algo que aconteceu. Diferente do @Input o @Output, não é declarado como uma variável simples, mas como um EventEmitter que vem do @angular/core , o EventEmitter tem um método chamado emit que serve para enviar uma atualização de estado para o elemento pai.

export class FilhoComponent {
	valor: any = null;
	@Output() evento = new EventEmitter<any>();
	
	// Método no componente filho para emitir o evento
	emitirEvento() {
	  this.evento.emit(valor);
	}
}

É necessário que tenha também um método no elemento pai que será executado e receberá essa atualização.

export class PaiComponent {
	receberEvento(dadoAtualizado: any) {
		//usar o dado para algo
	}
}

Para o componente filho entender que precisa receber as atualizações do evento nesse método do elemento pai, fazemos a repasse do método para o componente:

<app-filho (evento)="receberEvento($event)"></app-filho>
  • (evento) é o nome que foi dado ao evento no elemento filho;
  • receberEvento é o nome do método que receberá a atualização do dado no elemento pai;
  • ($event) é um parâmetro obrigatório que representa os dados

Para resumir, precisamos de um método no elemento pai que receberá a atualização do dado em questão, no elemento filho criamos um variável EventEmitter que armazenará o dado, e para atualizar o elemento pai, fazemos uma método no elemento filho que faz um emit.

Input e Output

Sabemos que o não podemos alterar uma variável @Input e não podemos receber do elemento pai um estado inicial quando usado o @Output.

Vamos supor que eu tenho dois elementos filhos e eu tenho um dado que preciso que ambos os elementos saibam e alterem o estado dele, seria então um dado compartilhado. Como faríamos para resolver esse problema? Se usássemos @Output eu conseguiria alterar esse dado pelo componente filho, mas como faríamos para o outro elemento filho saber dessa atualização? Isso não funciona porque só conseguimos enviar informação do pai para o filho pelo @Input, a solução então seria usar os dois ao mesmo tempo. Assim receberíamos as alterações e conseguiríamos enviar nossas atualizações de estado.

No elemento pai ficaria assim:

export class PaiComponent {
  dados: string = 'Dados iniciais do componente pai';

  atualizarDados(novosDados: string) {
    this.dados = novosDados;
  }
}
<app-filho [dados]="dados" (dadosAtualizados)="atualizarDados($event)"></app-filho>

E nos elementos filhos:

export class FilhoComponent {
	@Input() dados: string;
	@Output() dadosAtualizados = new EventEmitter<string>();
	
	dadosRecebidos: string;
	
	ngOnChanges() {
		this.dadosRecebidos = this.dados;
	}
	
	atualizarDados() {
	const novosDados = 'Novos dados do componente filho';
	this.dadosAtualizados.emit(novosDados);
	}
}
<p>Dados recebidos do pai: {{ dadosRecebidos }}</p>
<button (click)="atualizarDados()">Atualizar Dados</button>
  • 0 respostas
  1. Progress
    with doing this idea
  2. G@guilhduarte closed this topic 2024-01-16 16:53:35.275Z.
  3. G@guilhduarte reopened this topic 2024-01-16 16:53:39.062Z.