# Aula 4.2 - Templates, bindings e control flow

## Identificação

- **Duração:** 2 horas
- **Tipo:** teoria aplicada e laboratório
- **Entrega:** lista dinâmica de tarefas
- **Laboratório:** [`../exemplos/aula-4.2/index.html`](../exemplos/aula-4.2/index.html)

## Introdução

### O que é um template Angular?

Template é a descrição da view de um componente. Ele se baseia em HTML e acrescenta
sintaxes para conectar dados, propriedades, eventos e estruturas condicionais.

```html
<h2>{{ title }}</h2>
<button [disabled]="tasks().length === 0">Limpar</button>
```

Angular compila o template. O navegador não interpreta `{{ }}`, `[ ]`, `( )` ou
`@if` por conta própria.

### Template Angular é HTML puro?

Não. Grande parte do HTML continua válida, mas alguns caracteres possuem significado
especial:

- `{{ expression }}`: interpolação de texto;
- `[property]="expression"`: property binding;
- `[attr.name]="expression"`: attribute binding;
- `[class.name]="condition"`: class binding;
- `(event)="handler()"`: event binding;
- `@if`, `@for`, `@switch`: control flow.

### O que é binding?

Binding é uma conexão dinâmica entre o estado do componente e seu template. Quando o
estado utilizado muda, Angular atualiza a parte relacionada da interface.

Nem todo valor no HTML é binding:

```html
<button type="button">Salvar</button>
```

`type="button"` é estático.

```html
<button [disabled]="saving()">Salvar</button>
```

`disabled` depende do estado.

### Property e attribute são a mesma coisa?

Não. O HTML inicial possui atributos; o navegador cria objetos DOM com propriedades.
Em Angular, `[disabled]` altera a propriedade do botão. Para atributos sem
propriedade equivalente ou para ARIA, usamos binding de atributo:

```html
<button [attr.aria-pressed]="selected()">
```

### O que é control flow?

É a sintaxe que decide quais partes do template serão criadas:

```html
@if (tasks().length > 0) {
  <p>Existem tarefas.</p>
} @else {
  <p>Nenhuma tarefa.</p>
}
```

Ela se parece com estruturas do JavaScript, mas pertence ao compilador de templates
do Angular.

### `@for` é igual ao `for` do JavaScript?

Os dois repetem, mas rodam em contextos diferentes. `@for` produz e atualiza views.
Ele exige uma expressão `track` para relacionar cada item ao elemento correspondente.

```html
@for (task of tasks(); track task.id) {
  <li>{{ task.title }}</li>
}
```

### Por que `track` importa?

Sem identidade estável, o framework teria dificuldade para saber qual item mudou,
foi removido ou apenas mudou de posição. `task.id` permite preservar a relação entre
dado e DOM e reduzir operações desnecessárias.

Não use `$index` para listas que podem ser reordenadas, inseridas ou removidas quando
existe um identificador real.

### O que é `@empty`?

É o bloco exibido quando o `@for` não possui itens:

```html
@for (task of tasks(); track task.id) {
  <app-task-card />
} @empty {
  <p>Nenhuma tarefa encontrada.</p>
}
```

### Como isso entra na Knowledge AI?

Criaremos uma lista que apresenta tarefas, permite alternar conclusão, filtrar o
resultado e mostra um estado vazio acessível.

## Objetivos

Ao final da aula, o aluno deverá conseguir:

1. explicar o que é template Angular;
2. diferenciar HTML estático e binding;
3. utilizar interpolação;
4. criar property bindings;
5. criar attribute bindings;
6. aplicar class e style bindings;
7. responder a eventos;
8. utilizar `$event` com cuidado;
9. criar condições com `@if`;
10. repetir itens com `@for`;
11. escolher uma expressão `track` estável;
12. representar lista vazia com `@empty`.

## Pré-requisitos

- Aula 4.1 concluída;
- componentes, classe TypeScript e template;
- arrays, eventos e funções.

## Pergunta orientadora

> Como declarar uma interface dinâmica sem manipular manualmente cada elemento do DOM?

## Roteiro sugerido

| Etapa | Duração |
|---|---:|
| Template e expressões | 20 min |
| Bindings | 35 min |
| Eventos | 20 min |
| Control flow | 30 min |
| Laboratório | 10 min |
| Revisão | 5 min |

## 1. Template externo e inline

Externo:

```ts
@Component({
  templateUrl: "./task-list.html",
})
```

Inline:

```ts
@Component({
  template: `<h2>{{ title }}</h2>`,
})
```

Templates pequenos podem ser inline. Arquivos separados ajudam quando a view cresce.

## 2. Interpolação

```html
<h2>{{ heading }}</h2>
<p>{{ tasks().length }} tarefas</p>
```

O resultado é convertido em texto. Angular trata a interpolação como binding, não
como concatenação manual de HTML.

## 3. Interpolação não é `innerHTML`

```html
<p>{{ userText }}</p>
```

O valor é apresentado como texto. Não use `[innerHTML]` para contornar isso com
conteúdo não confiável. HTML dinâmico exige análise de segurança específica.

## 4. Expressões de template

Templates permitem leitura de propriedades, chamadas, operadores e expressões
controladas:

```html
<p>{{ task.title.toUpperCase() }}</p>
```

Evite cálculos caros e lógica de negócio extensa. Extraia para estado derivado,
métodos simples ou serviços.

## 5. Signals no template

Nesta aula, o estado mutável será guardado em signals:

```ts
tasks = signal<Task[]>(initialTasks);
```

No template, lemos chamando:

```html
<p>{{ tasks().length }}</p>
```

Signals serão aprofundados na Aula 4.8. Aqui eles apenas fornecem estado reativo para
praticar bindings.

## 6. Property binding

```html
<button [disabled]="tasks().length === 0">
  Limpar
</button>
```

Os colchetes informam que o valor é uma expressão e será escrito na propriedade DOM
ou em um input de componente.

Sem colchetes:

```html
<button disabled="false">
```

O atributo continua presente e o botão pode permanecer desabilitado. Booleanos não
devem ser representados como texto dessa forma.

## 7. Attribute binding

```html
<section [attr.aria-label]="listLabel()">
```

Use `attr.` quando precisar controlar um atributo. Se o valor resultar em `null`, o
Angular remove o atributo.

## 8. ARIA binding

```html
<button
  type="button"
  [attr.aria-pressed]="showCompleted()"
>
  Mostrar concluídas
</button>
```

Binding não substitui HTML semântico. Um botão continua precisando ser um `<button>`.

## 9. Class binding

```html
<article [class.is-done]="task.status === 'done'">
```

A classe é adicionada quando a expressão é truthy e removida quando falsy.

Também é possível vincular `class` a string, array ou objeto, mas prefira a forma
mais legível para o caso.

## 10. Style binding

```html
<progress
  [style.--completion]="completion() + '%'"
></progress>
```

Para valores numéricos com unidade:

```html
<div [style.width.%]="completion()"></div>
```

Não use estilos inline para substituir toda a arquitetura CSS.

## 11. Event binding

```html
<button type="button" (click)="toggleTask(task.id)">
  Alternar
</button>
```

Os parênteses conectam um evento a uma expressão. O método fica na classe do
componente.

## 12. O objeto `$event`

```html
<input (input)="updateQuery($event)">
```

`$event` representa o evento. No TypeScript, valide o target:

```ts
updateQuery(event: Event): void {
  if (event.target instanceof HTMLInputElement) {
    this.query.set(event.target.value);
  }
}
```

Não use assertions sem verificar o elemento real.

## 13. Evitar manipuladores complexos no HTML

Ruim:

```html
<button (click)="tasks.set(tasks().filter(...).map(...))">
```

Melhor:

```html
<button (click)="clearCompleted()">
```

O template comunica intenção e a classe implementa a operação testável.

## 14. `@if`

```html
@if (loading()) {
  <p>Carregando...</p>
} @else {
  <app-task-list />
}
```

O bloco controla se aquela view existe. Não é apenas esconder com CSS.

## 15. `@else if` e `@else`

```html
@if (error()) {
  <p role="alert">{{ error() }}</p>
} @else if (tasks().length === 0) {
  <p>Nenhuma tarefa.</p>
} @else {
  <app-task-list />
}
```

Ordene condições do estado mais específico para o conteúdo normal.

## 16. Alias em `@if`

```html
@if (selectedTask(); as task) {
  <h2>{{ task.title }}</h2>
}
```

O alias evita repetir uma expressão longa e restringe o valor ao bloco.

## 17. `@for`

```html
@for (task of visibleTasks(); track task.id) {
  <article>
    <h3>{{ task.title }}</h3>
  </article>
}
```

O bloco cria uma view por item e usa `task.id` para acompanhar sua identidade.

## 18. Escolhendo `track`

Preferência:

```text
identificador único e estável → task.id
lista realmente estática → $index
último recurso → referência do item
```

O valor não deve mudar durante a vida lógica do item.

## 19. Variáveis contextuais

```html
@for (
  task of visibleTasks();
  track task.id;
  let position = $index, last = $last
) {
  <p>Tarefa {{ position + 1 }}</p>
}
```

Também existem `$count`, `$first`, `$even` e `$odd`.

## 20. `@empty`

```html
@for (task of visibleTasks(); track task.id) {
  <app-task-card />
} @empty {
  <p>Nenhuma tarefa corresponde ao filtro.</p>
}
```

O bloco deve aparecer imediatamente após o conteúdo do `@for`.

## 21. `@switch`

```html
@switch (task.status) {
  @case ("todo") { <span>A fazer</span> }
  @case ("doing") { <span>Em andamento</span> }
  @case ("done") { <span>Concluída</span> }
  @default { <span>Status desconhecido</span> }
}
```

Não existe fallthrough como no `switch` tradicional.

## 22. Estado derivado

```ts
visibleTasks = computed(() => {
  return this.tasks().filter((task) => {
    return this.showCompleted() || task.status !== "done";
  });
});
```

O template lê `visibleTasks()` sem repetir a regra de filtro.

## 23. Atualização imutável

```ts
toggleTask(id: number): void {
  this.tasks.update((tasks) =>
    tasks.map((task) =>
      task.id === id
        ? { ...task, status: task.status === "done" ? "todo" : "done" }
        : task,
    ),
  );
}
```

Uma nova referência torna a mudança explícita e preserva outros itens.

## 24. Laboratório guiado

Abra a [lista dinâmica](../exemplos/aula-4.2/index.html).

### Etapa 1 — Alterne o filtro

Observe property, attribute e class bindings refletidos na prévia.

### Etapa 2 — Conclua tarefas

O event binding chama uma operação por identificador. O item conserva identidade.

### Etapa 3 — Esvazie o resultado

Use o filtro e remova itens até aparecer o equivalente ao bloco `@empty`.

### Etapa 4 — Examine a fonte

Alterne entre TypeScript e template. Relacione cada controle visual à sintaxe Angular
equivalente.

## 25. Sobre o laboratório estático

O laboratório abre sem instalar Angular e reproduz o comportamento com JavaScript.
A pasta `src/app` contém a fonte Angular equivalente. O objetivo é isolar a sintaxe
de templates antes da instalação do espaço de trabalho completo.

## 26. Erros comuns

### Usar atributo textual para booleano

`disabled="false"` ainda mantém o atributo. Use `[disabled]="condition"`.

### Usar índice como identidade de lista mutável

Inserções e reordenação podem associar view ao item errado.

### Colocar regra de negócio no template

Expressões ficam longas, repetidas e difíceis de testar.

### Usar `$event.target` sem narrowing

O target pode não ser o elemento esperado.

### Esconder estado vazio

Uma lista sem itens precisa explicar o resultado ao usuário.

### Usar `innerHTML` com entrada externa

Binding de texto é a escolha segura para conteúdo textual.

## 27. Boas práticas

- mantenha templates declarativos;
- use elementos semânticos;
- escolha a categoria correta de binding;
- trate eventos em métodos claros;
- use signals para estado mutável do template;
- derive filtros fora da marcação;
- use identificadores estáveis em `track`;
- implemente `@empty`;
- mantenha foco e mensagens acessíveis;
- evite HTML dinâmico não confiável.

## 28. Exercícios

### Exercício 1 — Interpolação

Mostre título e quantidade total de tarefas.

### Exercício 2 — Propriedade

Desabilite um botão quando a lista estiver vazia.

### Exercício 3 — Evento

Implemente `toggleTask(id)`.

### Exercício 4 — Control flow

Crie estados loading, error, lista e vazio.

### Exercício 5 — Track

Explique por que `task.id` é melhor que `$index` para a lista editável.

## 29. Desafio

Crie uma lista que:

- filtre por texto e status;
- mostre quantidade visível;
- utilize `@for` com `track task.id`;
- possua `@empty`;
- alterne conclusão por evento;
- associe `aria-pressed` ao filtro;
- desabilite ações impossíveis;
- não execute regra extensa no template.

## 30. Lista de verificação de conclusão

- [ ] Sei o que Angular compila no template.
- [ ] Diferencio texto estático e interpolação.
- [ ] Diferencio property e attribute binding.
- [ ] Uso class e style binding.
- [ ] Respondo a eventos.
- [ ] Faço narrowing de `$event.target`.
- [ ] Uso `@if` e `@else`.
- [ ] Uso `@for` com identidade estável.
- [ ] Sei quando não usar `$index`.
- [ ] Represento lista vazia com `@empty`.

## 31. Critérios de avaliação

| Critério | Pontos |
|---|---:|
| Interpolação e expressões | 15 |
| Property e attribute bindings | 20 |
| Eventos | 15 |
| `@if` e estados | 15 |
| `@for`, `track` e `@empty` | 25 |
| Acessibilidade e clareza | 10 |
| **Total** | **100** |

## Resumo

Nesta aula, aprendemos que:

- template Angular é HTML compilado com sintaxes adicionais;
- binding conecta estado e view;
- propriedade DOM e atributo HTML não são iguais;
- eventos chamam comportamentos da classe;
- `@if` cria views condicionais;
- `@for` repete e acompanha itens;
- `track` requer identidade estável;
- `@empty` representa coleção vazia;
- lógica complexa deve sair do template.

## Próxima aula

Na Aula 4.3, separaremos a lista e os cartões em componentes reutilizáveis e
criaremos comunicação explícita com inputs e outputs.

## Fontes oficiais

- [Visão geral de templates](https://angular.dev/guide/templates)
- [Binding de texto, propriedades e atributos](https://angular.dev/guide/templates/binding)
- [Control flow](https://angular.dev/guide/templates/control-flow)
- [Two-way binding](https://angular.dev/guide/templates/two-way-binding)
