Experts in Angular

Guias DetalhadoO Guia Estelar para Componentes Angular: selectors

O Guia Estelar para Componentes Angular: selectors

A Identidade Secreta dos Componentes: Seletores CSS

Cada nave da sua frota estelar tem um nome secreto que a identifica. É como um código que só os outros componentes conhecem. Esse código secreto é chamado de “seletor CSS”.

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

@Component({
  selector: 'app-exploration-craft',
  standalone: true,
  imports: [],
  template: `
    <div>🚀 Exploration Craft: Equipado para longas jornadas e exploração de novos planetas.</div>
  `,
  styles: ``
})
export class ExplorationCraftComponent {

}

Para chamar uma nave específica, você precisa usar o seu código secreto no template de outro componente:

import { Component } from '@angular/core';
import {ExplorationCraftComponent} from "./exploration-craft/exploration-craft.component";

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ExplorationCraftComponent],
  template: `
    <h1>Welcome to {{title}}!</h1>    
    <app-exploration-craft></app-exploration-craft>
  `,
  styles: [],
})
export class AppComponent {
  title = 'Frota de Naves Espaciais';
}

Embora o nome sugira uma ligação direta com CSS, no Angular, ele serve principalmente para identificar e instanciar componentes em sua aplicação. O termo “seletor” no Angular é derivado do uso semelhante de sintaxe para selecionar elementos no DOM, embora sua função seja diferente.

Um Código Secreto, Uma Nave

É importante lembrar que cada código secreto só pode ser usado para identificar uma única nave. Se você tentar usar o mesmo código para duas naves diferentes, o Angular vai ficar confuso e não saber qual nave chamar. É como tentar chamar dois super-heróis com o mesmo nome!

Letras Maiúsculas e Minúsculas Importam!

Os códigos secretos são muito sensíveis. Se você escrever o código com letras maiúsculas quando deveria ser minúsculo (ou vice-versa), o Angular não vai reconhecer a nave. É como digitar a senha errada do seu computador: você não consegue entrar!

Desvendando o Mistério dos Seletores

Angular usa os seletores CSS para identificar os componentes e saber onde eles devem ser exibidos na tela. É como um mapa estelar que mostra a localização de cada nave na galáxia.

Pontos Chave

  1. Combinação Estática em Tempo de Compilação:
    • O Angular resolve seletores de componentes durante a compilação, antes do tempo de execução. Isso significa que os componentes são associados a seus seletores antes da aplicação ser executada.
  2. Alterações no DOM em Tempo de Execução:
    • Alterações no DOM feitas em tempo de execução (por meio de bindings ou APIs DOM) não afetarão os componentes que foram renderizados. A associação dos seletores é estática e determinada na compilação.
  3. Correspondência de Seletores:
    • Um elemento no DOM deve corresponder exatamente a um seletor de componente para que o componente seja instanciado. Se vários seletores de componentes corresponderem a um único elemento, o Angular reportará um erro, pois não pode determinar qual componente instanciar.
  4. Diferenciação de Maiúsculas e Minúsculas:
    • Seletores de componentes diferenciam maiúsculas de minúsculas.
      Portanto, <app-cargo-ship></app-cargo-ship> corresponde ao seletor app-cargo-ship, mas <strong><em><App-Cargo-Ship></App-Cargo-Ship></em></strong> não corresponderia.

Desvendando os Códigos Secretos: Tipos de Seletores

Os códigos secretos das naves (seletores CSS) podem ser escritos de diferentes maneiras. Cada tipo de código tem seu próprio significado e serve para identificar naves com características específicas.

Tipo de SeletorDescriçãoExemplos
Seletor de TipoCorresponde a elementos com base no nome da tag HTML ou nome do nó.profile-photo
Seletor de AtributoCorresponde a elementos com base na presença de um atributo HTML e, opcionalmente, um valor exato para esse atributo.[dropzone] [type="reset"]
Seletor de ClasseCorresponde a elementos com base na presença de uma classe CSS..menu-item
O Angular oferece suporte a um subconjunto limitado de tipos básicos de seletores CSS em seletores de componentes

1. Seletor de Tipo (Type Selector)

Esse tipo de código secreto identifica naves pelo seu modelo. É como dizer “Chame todas as naves do tipo X-Wing!”

selector: 'x-wing'//Chama todos os elementos <x-wing>

2. Seletor de Atributo (Attribute Selector)

Esse código secreto identifica naves que possuem um certo equipamento ou acessório. É como dizer “Chame todas as naves com um canhão de laser!”

selector: '[laser-cannon]',  // Chama todos os elementos com o atributo laser-cannon
selector: '[type="starfighter"]', // Chama todos os elementos do tipo "starfighter"

3. Seletor de Classe (Class Selector)

Esse código secreto identifica naves que pertencem a um certo esquadrão. É como dizer “Chame todas as naves do Esquadrão Rebelde!”

selector: '.rebel-squadron',// Chama todos os elementos com a classe rebel-squadron

Dicas de Uso:

  • Seletor de Tipo: Use quando o componente deve ser aplicado a elementos com um nome específico, como <x-wing>.
  • Seletor de Atributo: Use quando o componente deve ser aplicado a elementos com um determinado atributo ou valor de atributo, como [laser-cannon].
  • Seletor de Classe: Use quando o componente deve ser aplicado a elementos que pertencem a uma determinada classe CSS, como .rebel-squadron.

Códigos Secretos Especiais

Existem algumas regras importantes para usar os códigos secretos:

  • Sem Combinadores: Você não pode usar códigos secretos que combinem diferentes características. É como tentar chamar “todas as naves X-Wing do Esquadrão Rebelde com um canhão de laser”.
  • Sem Suporte para namespaces: os seletores de componentes Angular não suportam a especificação de namespaces em seus seletores CSS.

O que são combinadores em CSS?

Combinadores em CSS são usados para definir a relação entre os seletores e especificar como os elementos devem ser combinados.

Combinador de descendente ():

Seleciona elementos que são descendentes de um determinado elemento.

/* Seleciona todos os elementos <span> que são descendentes de <div> */
div span {
  color: blue;
}

Combinador de filho (>):

Seleciona elementos que são filhos diretos de um determinado elemento.

/* Seleciona todos os elementos <span> que são filhos diretos de <div> */
div > span {
  color: blue;
}

Limitações do Angular:

Os seletores de componentes Angular não suportam esses combinadores. Em outras palavras, você não pode definir um seletor de componente Angular que use combinadores para selecionar elementos baseados em suas relações hierárquicas.

Exemplo de combinadores que não são suportados:

  • Combinador de descendente:
@Component({
  selector: 'div span', // Isso não é suportado pelo Angular
  templateUrl: './descendant-component.component.html',
  styleUrls: ['./descendant-component.component.css']
})
export class DescendantComponent {
  // Lógica do componente
}
  • Combinador de filho:
@Component({
  selector: 'div > span', // Isso não é suportado pelo Angular
  templateUrl: './child-component.component.html',
  styleUrls: ['./child-component.component.css']
})
export class ChildComponent {
  // Lógica do componente
}

No Angular, você pode usar seletores de tipo, atributo e classe para definir componentes, mas não pode usar combinadores CSS para selecionar elementos com base em suas relações hierárquicas. Isso significa que seletores como div span ou div > span não são válidos em seletores de componentes Angular. Cada seletor de componente deve ser simples e direto, sem especificar combinações complexas de elementos.

O que são namespaces em CSS?

Namespaces em CSS são usados principalmente em XML e SVG para distinguir entre elementos que têm o mesmo nome, mas pertencem a diferentes vocabulários ou esquemas de nomenclatura. Em CSS, você pode prefixar seletores com um namespace para aplicar estilos apenas a elementos que pertencem a esse namespace.

Exemplo de namespace em CSS:

/* Seleciona todos os elementos <button> no namespace "svg" */
svg|button {
  fill: blue;
}

No exemplo acima, svg|button é um seletor que aplica estilos apenas aos elementos <button> dentro do namespace svg.

Limitações do Angular:

Quando a documentação diz que “Sem Suporte para namespaces“, isso significa que você não pode usar seletores com namespaces em componentes Angular. Em outras palavras, você não pode criar um seletor de componente Angular que use um prefixo de namespace como svg|button.

Exemplo que não é suportado:

@Component({
  selector: 'svg|button', // Isso não é suportado pelo Angular
  templateUrl: './svg-button.component.html',
  styleUrls: ['./svg-button.component.css']
})
export class SvgButtonComponent {
  // Lógica do componente
}

O Poder da Exclusão: O Pseudo-Classe :not

Imagine que você quer chamar todas as naves para a batalha, exceto as naves de transporte. É aí que entra o poder da exclusão! O pseudo-classe :not permite que você chame todas as naves que não possuem uma certa característica.

@Component({
  selector: '[dropzone]:not(textarea)',
  template: `<div>Dropzone sem suporte a textarea</div>`,
})
export class DropZone { }

Nesse exemplo, o código secreto chama todos os elementos que possuem o atributo dropzone, exceto os elementos do tipo textarea. É como dizer “Chamem todas as naves de combate, mas deixem as naves de transporte no hangar!”

O Único Pseudo-Classe Permitido

O :not é o único pseudo-classe que você pode usar nos códigos secretos dos componentes. Angular não permite outros pseudo-classes ou pseudo-elementos, como :hover ou ::before.

  • Angular suporta a pseudo-classe :not: Você pode usar :not em seletores de componentes Angular para excluir elementos específicos de uma correspondência de seletor.
  • Outras pseudo-classes e pseudo-elementos não são suportados: Você não pode usar outras pseudo-classes como :hover ou pseudo-elementos como ::before em seletores de componentes Angular.

Combinando Códigos Secretos: Seletores Múltiplos

Às vezes, você precisa chamar naves com características diferentes para a mesma missão. É como montar uma equipe com naves de combate, naves de reconhecimento e naves de transporte. Para isso, você pode combinar vários códigos secretos em um só!

1. Concatenando Códigos Secretos

Você pode juntar dois ou mais códigos secretos para chamar naves que possuem todas as características desejadas. É como dizer “Chame todas as naves X-Wing do Esquadrão Rebelde!”

@Component({
  selector: 'button[type="reset"]', // Chama todos os botões do tipo "reset"
  // ... (outras configurações)
})
export class ResetButton { }

2. Lista de Códigos Secretos

Você também pode criar uma lista de códigos secretos, separados por vírgula. Nesse caso, o Angular chamará todas as naves que corresponderem a qualquer um dos códigos da lista. É como dizer “Chame todas as naves X-Wing ou Y-Wing!”

@Component({
  selector: 'input[type="text"][required]',
  templateUrl: './text-input.component.html',
  styleUrls: ['./text-input.component.css']
})
export class TextInputComponent {
  // Chama todos os elementos <input> que são do tipo "text" e têm o atributo "required"
}
@Component({
  selector: 'app-button, [app-button]',
  templateUrl: './app-button.component.html',
  styleUrls: ['./app-button.component.css']
})
export class AppButtonComponent {
  // Chama todos os elementos <app-button> e todos os elementos com o atributo [app-button]
}
  • Combinando Seletores: Você pode combinar seletores para criar seletores mais específicos. Por exemplo, button[type="reset"] aplicará o componente a botões que são do tipo “reset”.
  • Múltiplos Seletores: Você pode definir múltiplos seletores usando uma lista separada por vírgulas. Por exemplo, drop-zone, [dropzone] aplicará o componente a elementos <drop-zone> e elementos com o atributo dropzone.

Escolhendo o Nome da Nave: Elementos Personalizados

Assim como cada nave tem um nome único, cada componente Angular deve ter um nome especial que o identifique. Esse nome é chamado de “elemento personalizado” e deve seguir algumas regras importantes.

A Regra do Hífen

O nome do seu componente deve sempre incluir um hífen (-). É como o nome de um super-herói: ele precisa ter um traço para ser reconhecido como tal. Por exemplo, profile-photo é um nome válido, enquanto profilephoto não é.

Por que o Hífen?

O hífen ajuda o Angular a distinguir seus componentes dos elementos HTML padrão. Imagine que você criou um componente chamado button. Se você não usar o hífen, o Angular pode confundir o seu componente com o elemento <button> do HTML.

O Detector de Erros do Angular

O Angular é como um radar que detecta erros em sua frota estelar. Se você tentar usar um componente que não existe, ele vai te avisar. Isso ajuda a evitar problemas e garantir que sua interface funcione perfeitamente.

Identificando as Naves da Sua Frota: Prefixos de Seletor

Imagine que você está em uma batalha espacial com várias frotas aliadas. Para evitar confusão e garantir que cada nave seja identificada corretamente, cada frota usa um prefixo especial em seus nomes. É como um distintivo que mostra a qual equipe a nave pertence.

Prefixos Personalizados

Em seus projetos Angular, você também pode usar prefixos para identificar seus componentes. Por exemplo, se você estivesse construindo o YouTube com Angular, poderia usar o prefixo yt- para seus componentes, como yt-menu, yt-player, etc.

Usar prefixos personalizados ajuda a organizar seus componentes e evita conflitos com outros projetos ou bibliotecas. É como ter um uniforme especial para sua frota estelar!

O Prefixo Padrão do Angular CLI

Quando você cria um novo projeto Angular usando o Angular CLI, ele automaticamente adiciona o prefixo app- aos seus componentes. Você pode manter esse prefixo ou escolher um personalizado que faça mais sentido para o seu projeto.

O Prefixo Reservado ng

O Angular usa o prefixo ng para seus próprios componentes e diretivas. É como o distintivo da Frota Estelar da Federação! Nunca use o prefixo ng para seus próprios componentes, para evitar conflitos com os componentes do Angular.

Quando Chamar Reforços: Seletores de Atributos

Imagine que você precisa personalizar uma nave já existente na sua frota, como adicionar um canhão de laser extra a um X-Wing. É aí que entram os seletores de atributos! Eles permitem que você modifique o comportamento de um elemento HTML padrão, transformando-o em um componente Angular.

Você deve considerar usar um seletor de atributo quando deseja criar um componente que seja aplicado a um elemento nativo padrão. Isso permite que você aproveite as APIs padrão do elemento sem trabalho adicional.

Botões Turbinados

Por exemplo, se você quiser criar um botão especial para enviar vídeos para o YouTube, pode usar um seletor de atributo para transformar um botão HTML comum em um componente Angular:

@Component({
  selector: 'button[yt-upload]', // Transforma botões com o atributo yt-upload em componentes Angular
   ...
})
export class YouTubeUploadButton { }

Com essa técnica, você pode aproveitar todas as funcionalidades do botão HTML original, como acessibilidade e eventos de clique, e ainda adicionar superpoderes extras com o Angular.

import { Component } from '@angular/core';
import {YtMenuComponent} from "./yt-menu/yt-menu.component";
import {YtPlayerComponent} from "./yt-player/yt-player.component";
import {YoutubeUploadButtonComponent} from "./youtube-upload-button/youtube-upload-button.component";

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ YtMenuComponent,
    YtPlayerComponent,
    YoutubeUploadButtonComponent],
  template: `
    <h1>Welcome to {{title}}!</h1>

    <yt-menu></yt-menu>
    <yt-player></yt-player>
    <button yt-upload></button>
  `,
  styles: [],
})
export class AppComponent {
  title = 'attribute-selector';
}

Confira o código no GitHub.

Vantagens de Usar Seletores de Atributos:

  1. Aproveitamento das APIs Padrão:
    • Ao usar um seletor de atributo em um elemento nativo, você pode aproveitar todas as APIs padrão do elemento sem trabalho adicional. Isso é especialmente valioso para atributos ARIA, como aria-label, que ajudam na acessibilidade.
  2. Facilidade de Uso:
    • Os consumidores do componente podem usar diretamente o elemento nativo com o atributo personalizado, tornando o uso do componente mais intuitivo.
  3. Compatibilidade e Extensão:
    • Permite que você estenda a funcionalidade dos elementos nativos de forma compatível e padronizada.

Cuidado com as Importações!

Ao usar seletores de atributos, é importante lembrar de importar o componente para a sua frota. Se você esquecer de fazer isso, o Angular não saberá como transformar o elemento HTML em um componente.

Importação do Componente:

  • O Angular não gera erros quando encontra atributos personalizados que não correspondem a um componente disponível. Portanto, ao usar componentes com seletores de atributos, os consumidores podem esquecer de importar o componente ou seu NgModule, resultando na não renderização do componente.

Recomendação de Nomenclatura:

  • Os componentes que definem seletores de atributos devem usar atributos em caixa baixa (lowercase) e com hifens (dash-case). Seguir uma convenção de prefixo é recomendado para evitar conflitos de nomenclatura.
Exemplo de Uso Padrão:
<button yt-upload aria-label="Upload your video to YouTube"></button>

Prefixos para Evitar Confusão

Para evitar conflitos com outros projetos ou bibliotecas, é recomendado usar prefixos nos seus seletores de atributos. Por exemplo, no caso do botão de envio para o YouTube, usamos o prefixo yt-.