# Angular
Trabalhando com angular-cli.
> Angular é uma plataforma de aplicações web de código-fonte aberto e front-end baseado em TypeScript liderado pela Equipe Angular do Google e por uma comunidade de indivíduos e corporações. Angular é uma reescrita completa do AngularJS, feito pela mesma equipe que o construiu.
> [--Wiki](https://g.co/kgs/guUR7X)
<!-- ## Table of Contents
TODO -->
---
## Anexos
- [Adicionar Libs de estilo ao projeto: Bootstrap, Materialize](https://github.com/layshidani/my-learning-notes/blob/master/angular/angular-bootstrap.md)
<!-- TODO - [Typescrip]() -->
---
# Preparando o ambiente de desenvolvimento com Angular cli
[Angular cli reference](https://angular.io/cli)
Pre-requisitos:
- NodeJS instalado
```bash
sudo npm i -g @angular/cli
```
```bash
sudo npm i -g typescript
```
## Iniciar um novo projeto com o Angular cli
```bash
ng new app-name
```
Entre no diretório do projeto para começar a trabalhar nele:
```bash
cd app-name
```
## Rodando a aplicação
O comando abaixo irá fazer o build da aplicação e rodar no [http://localhost:4200/](http://localhost:4200/), você poderá acompanhar pelo browser o efeito das alterações do projeto.
```bash
ng serve
```
ou abreviado:
```bash
ng s
```
---
# Componentes
> Angular 2 é orientado a componentes, isso significa que você vai escrever diversos componentes minúsculos que juntos constituirão uma aplicação inteira. Um Component é a combinação de um template HTML com uma classe que controla parte da tela.
> [--Matera](http://www.matera.com/blog/post/comecando-com-angular-2)
É possível criar os componentes manualmente ou de forma mais simplificada, utilizando o `angular-cli`.
Os arquivos de componentes estão em: **src >>> app**
## Criar componente utilizando o angular cli
Basta digitar no terminal:
```bash
ng g c nome-do-componente
```
ou se já existir o diretório:
```bash
ng g c diretorio/nome-do-componente
```
onde:
- g: gerar
- c: component
Esse comando irá criar a pasta do component e os arquivos.
Neste caso, ele também irá criar o arquivo html onde você deverá editar o conteúdo do seu component. É uma forma diferente da demonstrada no modo manual com template string, ambas as formas podem ser utizadas (template string, html separado).
No arquivo **nome-do-componente.component.ts**, gerado na criação do componente, haverá o seletor que você poderá usar no HTML, por exemplo:
No arquivo **btn.component.ts**:
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-btn", // este seletor
templateUrl: "./btn.component.html",
styleUrls: ["./btn.component.sass"]
})
export class BtnComponent implements OnInit {
constructor() {}
ngOnInit() {}
}
```
O seletor **app-btn**, poderá ser usado no html como:
```html
<app-btn></app-btn>
```
**!Nota: se o component estiver importado no app.module.ts que é o module raíz do projeto, você também poderá utilizar o component dentro dos arquivos html de outros components.**
**!Convenção: Criar nome das pastas e dos arquivos de componentes em Kebab Case (com letra minúscula e palavras separadas por "-")**
**!Convenção: classes são escritas em Pascal Case (todas as primeiras letras em maiúsculo)**
<!-- ## Criar o primeiro componente manualmente
**> Arquivos**
1. Cria a pasta nome
2. Cria o arquivo nome-component.ts
```ts
import { Component } from "@angular/core";
@Component({
// nome da tag
selector: "meu-primeiro-component",
// conteúdo da tag
template: `
<p>Meu primeiro component com Angular 2!</p>
`
})
export class MeuPrimeiroComponent {}
```
## Usar o component manualmente -->
<!-- Vá até o arquivo _.module.ts_.
Por exemplo, para usar no módulo raíz:
**app.module.ts**
1. Importe a classe:
2. Acrescente o component nas **declarations**.
Exemplo:
```ts
import { MeuPrimeiroComponent } from './meu-primeiro/meu-primeiro.component';
@NgModule({
declarations: [
AppComponent,
MeuPrimeiroComponent
],
```
Vá até o arquivo html que deseja adicionar. Por exemplo:
**app.component.html**
adicione o componente onde desejar:
```html
<meu-primeiro-component></meu-primeiro-component>
``` -->
## ng Content
Projeção de conteúdo:
```html
<app-example>
<ng-content></ng-content>
</app-example>
```
---
# Templates
**html = template**
!Boa prática: no Component -> Utilizar template string somente se tiver até 3 linhas. Mais do que isso é recomendado um arquivo HTML a parte.
## Interpolação e Diretivas
### Interpolação
Podemos usar a interpolação para atribuir valores em um componente.
```
{{ x }}
```
Por exemplo:
no arquivo **exemplo.component.ts**
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-exemplo",
templateUrl: "./exemplo.component.html",
styleUrls: ["./exemplo.component.sass"]
})
export class ExemploComponent implements OnInit {
myName: string;
constructor() {
this.myName = "Lays";
}
ngOnInit() {}
}
```
Depois de ter feito todos as configurações necessárias no arquivo de **modules**.
Podemos utilizar a interpolação no arquivo **exemplo.component.html**
```html
<h2>Olá, meu nome é {{ myName }}!</h2>
```
Inserindo o componente para exibição, o resultado será:
**Olá, meu nome é Lays**
<!-- ### Diretivas
Exemplo:
**no arquivo numbers.component.ts:**
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-numbers",
templateUrl: "./numbers.component.html",
styleUrls: ["./numbers.component.sass"]
})
export class NumbersComponent implements OnInit {
numbers: string[] = ["1", "2", "3"];
constructor() {}
ngOnInit() {}
}
```
**no arquivo numbers.component.html:**
```html
<ul>
<li *ngFor="let num of nums">{{ num }}</li>
</ul>
```
O resultado será:
- 1
- 2
- 3 -->
---
# Modules
> Em Angular, um módulo é um mecanismo para agrupar componentes, diretivas, canais e serviços relacionados, de forma que possam ser combinados com outros módulos para criar uma aplicação. Uma aplicação Angular pode ser vista como um quebra-cabeça onde cada peça (ou cada módulo) é necessária para poder ver a imagem completa.
> Outra analogia para entender os módulos angulares são as classes. Em uma classe, podemos definir **métodos públicos ou privados**. Os métodos públicos são a API que outras partes do nosso código podem usar para interagir com ela, enquanto os métodos privados são detalhes de implementação ocultos. Da mesma forma, um módulo pode exportar ou ocultar componentes, diretivas, tubulações e serviços. Os elementos exportados devem ser usados por outros módulos, enquanto os que não são exportados (ocultos) são usados apenas dentro do próprio módulo e não podem ser acessados diretamente por outros módulos de nosso aplicativo. [--Angular 2 training book](https://angular-2-training-book.rangle.io/modules/introduction)
O angular-cli cria automaticamente um arquivo **app.modules.ts**:
(esse é o módulo raiz do projeto)
```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppRoutingModule } from "./app-routing.module";
// importar components
// boa prática: agrupar os imports de components após pular uma linha dos imports iniciais
import { AppComponent } from "./app.component";
import { MeuPrimeiroComponent } from "./meu-primeiro/meu-primeiro.component";
import { Componente2Component } from "./componente2/componente2.component";
// declaratios, imports são metadados
@NgModule({
// declarations: componentes, diretivas e pipes
declarations: [AppComponent, MeuPrimeiroComponent, Componente2Component],
// import: outros módulos para serem utilizados dentro deste módulo ou de algum componente que pertence a este módulo
imports: [BrowserModule, AppRoutingModule],
// providers: serviçoes disponíveis para os componentes, e nesse caso, na aplicação global, já que AppModule é global:
providers: [],
// instanciado no carregamento da SPA:
bootstrap: [AppComponent]
})
export class AppModule {}
```
## Criar módulo
(esse é um módulo de funcionalidade do projeto)
Na pasta do projeto, digite no terminal:
```bash
ng g m nome-do-modulo
```
Ex:
```bash
ng g m my-module
```
irá criar um diretório com o nome do módulo (ex: my-module), com o arquivo **.ts** correspondente ao módulo criado:
```ts
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
@NgModule({
declarations: [],
imports: [CommonModule]
})
export class MyModuleModule {}
```
## Adicionar componentes ao módulo
ver como [criar componentes](https://github.com/layshidani/my-learning-notes/blob/master/angular/components.md)
O **angular-cli** cuida dos imports dos componentes que são criados e das declarações, acrescentando-os no **app.module.ts**.
Se você tiver a extensão [Auto Import](https://marketplace.visualstudio.com/items?itemName=steoates.autoimport), ela irá acrescentar os imports necessários dos componentes no arquivo de módulo, porém é necessário acrescentar o trecho de **export** para indicar o que deve ser efetivamente exportado e exibido.
```ts
,
exports: [
NomeDoComponent
]
```
Assim, nosso arquivo de exemplo fica assim:
```ts
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { BtnComponent } from "./btn.component";
@NgModule({
declarations: [BtnComponent],
imports: [CommonModule],
exports: [BtnComponent]
})
export class BtnModule {}
```
_!Dica: Importar módulo -> Sempre que estiver trabalhando com mais módulo além do módulo **app.module.ts**, será necessário **exportar** este módulo em seu arquivo e **importar** no arquivo raíz._
Depois disso será necessário importar o módulo de funcionalidade dentro do módulo raíz (app.module.ts).
Exemplo:
no arquivo **app.module.ts**:
Importar a classe:
```ts
import { BtnModule } from "./btn/btn.module";
```
Em seguida, importar o módulo no NgModule:
```ts
@NgModule({
declarations: [
AppComponent,
MeuPrimeiroComponent,
Componente2Component
],
imports: [
BrowserModule,
AppRoutingModule,
BtnModule // importar o módulo aqui
],
providers: [],
bootstrap: [AppComponent]
})
```
Também é possível fazer uso de componentes privados, não incluindo-os no imports.
**!Nota: se o component estiver importado no app.module.ts que é o module raíz do projeto, você também poderá utilizar o component dentro dos arquivos html de outros components.**
---
# Services e Injeção de Dependência
> O serviço é simplesmente uma função javascript, juntamente com suas propriedades e métodos associados, que podem ser incluídos (via injeção de dependência) nos componentes do Angular 2. Eles permitem desenvolver código para tarefas específicas que podem ser usadas nesses componentes. [--Coursetro](https://coursetro.com/posts/code/20/Angular-2-Services-Tutorial---Understanding-&-Creating-Them)
> Angular distingue componentes de serviços para aumentar a modularidade e a reutilização. Ao separar a funcionalidade relacionada à visualização de um componente de outros tipos de processamento, você pode tornar suas classes de componentes simples e eficientes. [--Angular.io](https://angular.io/guide/architecture-services)
Para criar na raiz do projeto (dir app):
```bash
ng g s service-name
```
Para criar em um diretório de componente já existente:
```bash
ng g s dir-name/service-name
```
Este comando irá criar dois arquivos:
- service-name.service.spec.ts
- service-name.service.ts
!Boas práticas fazer o uso de services para injetar dados, ao invés de fazer direto por diretiva.
Utilizando o mesmo exemplo das diretivas:
Seguimos 3 passos:
1. no arquivo **numbers.service.ts**:
```ts
import { Injectable } from "@angular/core";
// @injectable é um decorator
@Injectable({
providedIn: "root"
})
export class NumbersService {
constructor() {}
getNumbers() {
// adiciona um return com os valores a serem injetados:
return ["1", "2", "3"];
}
}
```
2. no arquivo **numbers.component.ts**:
```ts
import { Component, OnInit } from "@angular/core";
// importar a classe NumbersService
import { NumbersService } from "./numbers.service";
@Component({
selector: "app-numbers",
templateUrl: "./numbers.component.html",
styleUrls: ["./numbers.component.sass"]
})
export class NumbersComponent implements OnInit {
// retirar o array daqui e inserir no arquivo de service:
// numbers: string[] = ['1', '2', '3'];
numbers: string[];
// Instanciar via construtor (pode ser private ou public)
constructor(private numbersService: NumbersService) {
this.numbers = this.numbersService.getNumbers();
}
ngOnInit() {}
}
```
3. no arquivo **numbers.component.html**:
```html
<ul>
<li *ngFor="let num of nums">{{ num }}</li>
</ul>
```
Por fim,
O resultado será:
- 1
- 2
- 3
---
# Data binding
- [Ótima Documentação](https://angular.io/guide/template-syntax)
Associação de informações que estão no componente para o template e vice-e-versa.
**componente <----info----> template**
componente ---> template
- interpolação: `{{x}}`
- property binding: `[propriedade]='x'`
template ---> component:
- evento: `(event)='handler'`
componente <---> template:
- Two-way data binding: `[(ngModel)='property']`
> Two-way data binding: a sincronização entre o model e a view. Quando os dados no model são alterados, a view reflete a alteração e, quando os dados da view mudam, o model também é atualizado. [--w3schools](https://www.w3schools.com/angular/angular_databinding.asp)
## componente ---> template
Exemplos:
Dado o arquivo:
**example.components.ts**
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-example",
templateUrl: "./example.component.html",
styleUrls: ["./example.component.css"]
})
export class DataBindingComponent implements OnInit {
url: string = "https://github.com/layshidani/my-learning-notes/";
aprender: boolean = true;
urlImagem: string = "http://lorempixel.com/400/200/animals/";
getValor() {
return "Hello";
}
praticar() {
return true;
}
constructor() {}
ngOnInit() {}
}
```
- interpolação: `{{x}}`
**example.component.html**:
```html
<section>
<h3>Interpolation</h3>
<p>string rendereizada com interpolação: {{ url }}</p>
<p>Interpolação com expressões: 1 + 1 = {{ 1 + 1 }}</p>
<p>Interpolação com getValor: {{ getValor() }}</p>
<p>Com expressão bool: {{ aprender && praticar() }}</p>
<img src="{{urlImagem}}" />
</section>
```
O resultado do código acima será:
![Resultado interpolação](imgs/interpolation.png)
- property binding: `[propriedade]='x'`
Considerando o mesmo arquivo **example.components.ts**...
No html:
```html
<section>
<h3>Property Binding</h3>
<p>Property-biding (<code>[src]="urlImagem"</code>):</p>
<img [src]="urlImagem" />
<!-- Os métodos são equivalentes -->
<p>Que é o mesmo que (<code>bind-src="urlImagem"</code>):</p>
<img bind-src="urlImagem" />
</section>
```
O resultado do código acima será:
![Resultado Property Binding](imgs/property-binding.png)
**!Quando não houver uma property no elemento para ser utilizado no property-binding (como o src da img), pode-se utilizar como property:**
```html
[attr.colspan]="valor"
```
---
## Class Binding
> Adicione e remova nomes de classe CSS do atributo de classe de um elemento com uma vinculação de classe.
> Class Binding se parece com Property Biding, mas em vez de uma propriedade de elemento entre colchetes, começa com a classe de prefixo, opcionalmente seguida por um ponto (.) Eo nome de uma classe CSS: `[class.class-name]`. --[Angular guide](https://angular.io/guide/template-syntax)
Exemplo:
```html
<section>
<article>
<h3>Selecione uma classe:</h3>
<!-- #var = variável local do template para que seja possível acessar esse select l (template reference variable) -->
<select #classe (change)="0">
<option value="alert-success">Sucesso</option>
<option value="alert-danger">Erro</option>
</select>
</article>
<article>
<!-- [class.className]="expression" -->
<div
class="alert"
role="alert"
[class.alert-success]="classe.value == 'alert-success'"
>
A simple primary alert—check it out!
</div>
<div
class="alert"
role="alert"
[class.alert-danger]="classe.value == 'alert-danger'"
>
A simple primary alert—check it out!
</div>
</article>
</section>
```
Alguns exemplos retirados do [Guia](https://angular.io/guide/template-syntax):
```html
<h3>Substituir todas as class:</h3>
<div class="item clearance special" [attr.class]="resetClasses">
Reset all classes at once
</div>
```
```html
<h3>Add a class:</h3>
<div class="item clearance special" [class.item-clearance]="itemClearance">
Add another class
</div>
```
```html
<h3>toggle the "special" class on/off with a property:</h3>
<div [class.special]="isSpecial">The class binding is special.</div>
<h3>binding to class.special overrides the class attribute:</h3>
<div class="special" [class.special]="!isSpecial">
This one is not so special.
</div>
<h3>Using the bind- syntax:</h3>
<div bind-class.special="isSpecial">This class binding is special too.</div>
```
## Style Binding
> A sintaxe do Style binding se parece com a de Property Binding. Em vez de uma propriedade de elemento entre colchetes, comece com o estilo de prefixo, seguido por um ponto (.) E o nome de uma propriedade de estilo CSS: `[style.style-property]`. --[Guia](https://angular.io/guide/template-syntax)
Alguns exemplos:
```html
<button [style.color]="error ? 'red': 'green'">Red</button>
```
```html
<div
class="alert alert-danger"
role="alert"
[style.display]="classe.value == 'alert-danger' ? 'block' : 'none'"
>
Cuidado ERRO Selecionado
</div>
```
## Event Binding
[MDN - lista de eventos](https://developer.mozilla.org/en-US/docs/Web/Events)
Alguns exemplos de evento são:
- (click)="myFunction()"
- (submit)="myFunction()"
- (blur)="myFunction()"
- (focus)="myFunction()"
- (scroll)="myFunction()"
- (keyup)="myFunction()"
- (keypress)="myFunction()"
- (keydown)="myFunction()"
- (input)="myFunction()"
```html
<tag (target event name)="templateStatment()">Text</tag>
```
exemplo:
```html
<button (click)="onSave($event)">Save</button>
```
Outro exemplo:
no arquivo **event-example.component.html**:
```html
<h2
(mouseover)="onMouseOverOut()"
(mouseout)="onMouseOverOut()"
[class.highlight]="isMouseOver"
>
Passe o mouse sobre este texto :)
</h2>
```
no arquivo **event-example.component.ts**:
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-event-example",
templateUrl: "./event-example.component.html",
styles: [
`
.highlight {
background-color: green;
font-weight: bold;
}
`
]
})
export class EventExampleComponent implements OnInit {
isMouseOver: boolean = false;
onMouseOverOut() {
this.isMouseOver = !this.isMouseOver;
}
constructor() {}
ngOnInit() {}
}
```
no arquivo **app.component.html**:
```html
<app-data-binding></app-data-binding>
```
## Two-way Data Binding
Propriedade + evento
```ts
[()]="value"
```
_!Dica: Quando trabalhando com formulários, deverá importar o `@angular/forms` no arquivo de **module.ts**:_
```ts
// ...
// importa o módulo
import { FormsModule } from '@angular/forms'
@NgModule({
// ...
imports: [
//...
// add no imports
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
// ...
```
Exemplo:
Supondo um objeto chamado pet, que está no arquivo **component.ts**:
```ts
pet = {
name: "Dexter",
age: 2
};
```
No **component.html** teremos:
```html
<section>
<h3>Two-way Data Binding</h3>
<input type="text" [(ngModel)]="'Nome: ' + pet.name" />
<input type="text" [(ngModel)]="'Idade: ' + pet.age" />
<h4>Resultado:</h4>
<p>
Pet: Meu nome é {{ pet.name }} e tenho {{ pet.age }} ano(s) :)
</p>
</section>
```
## Input/Output Properties - Comunicação entre componentes
[IT Next - input/output tutorial.](https://itnext.io/angular-input-output-f0418ab4cc91)
Utilizar dados de um componente em outro.
Considere um componente pai e um componente filho:
- Input: de pai para filho (de fora para dentro)
- Output: de filho para pai (de dentro para fora)
### Input
> de pai para filho (de fora para dentro)
Por padrão, as propriedades de um componente só estão disponíveis para ele mesmo, se quisermos expo-las para outro componente, devemos utilizar o input.
No arquivo **filho.component.ts** importamos os dados do componente pai para que possam ser utilizados pelo componente filho:
```ts
// não esquecer de importar a classe Input do @angular/core
import { Component, OnInit, Input } from '@angular/core';
// ...
@Input() originalName: type;
// ou podemos usar um nome de variável diferente
@Input('originalName') alias: type;
```
no componente pai (**pai.component.html**) ao utilizarmos o componente filho através de sua tag, devemos 'disponibilizar/repassar' a variável correspondente ao dado através dos properties:
```html
<app-filho [variable]="variable"></app-filho>
<!-- ou para uso de hardCoded, valor cravado, não precisa de [] -->
<app-filho variable="10"></app-filho>
<!-- ou em caso de nome diferente -->
<app-filho [alias]="originalName"></app-filho>
```
Exemplo:
**pai.component.ts**:
```ts
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
title = "input";
esposa: string;
constructor() {
this.esposa = "Juliane";
}
}
```
**pai.component.html**
```html
<h1>Angular @Input()</h1>
<h2>Pai</h2>
<h3>Esposa do pai (* Valor original do pai):</h3>
<p>{{ esposa }}</p>
<hr />
<!-- Aqui, estamos passando utilizando um alias (esposaDoPai) para passar ao filho o valor de esposa que vem do pai -->
<app-filho [esposaDoPai]="esposa"></app-filho>
```
**filho.component.ts**
```ts
// import do Input no @angular/core
import { Component, OnInit, Input } from "@angular/core";
@Component({
selector: "app-filho",
templateUrl: "./filho.component.html",
styleUrls: ["./filho.component.css"]
})
export class FilhoComponent implements OnInit {
// Pega o Input do pai (esposaDoPai) e utiliza no filho como mãe
@Input("esposaDoPai") mae;
constructor() {}
ngOnInit() {}
}
```
**filho.component.html**
```html
<h2>Filho</h2>
<h3>Mãe do filho (Input vindo do pai):</h3>
<p>{{ mae }}</p>
```
Resultado:
![Exemplo Input](imgs/ex-input.png)
### Output
---
TODO escrever sobre:
- Output
- EventEmitter()
- ViewChild()
- ContentChild()
---
> de filho para pai (de dentro para fora)
```ts
// importar a classe Output do @angular/core
import { Component, OnInit, Output } from '@angular/core';
// utilizar o decorator @Output
@Output() originalName: type
// ou podemos usar um nome de variável diferente
@Output('alias') originalName: type
```
## Local reference
Pode ser utilizado em qualquer elemento HTML.
```html
<input #localReferenceName />
```
Exemplo:
```html
<!-- guardamos a referência local do select em #num -->
<!-- na mudança de opção ele passa o valor para a função selectedValue -->
<select #num (change)="selectedValue(num)">
<option value="1">1</option>
<option value="2">2</option>
</select>
<!-- mostramos o valor selecionado com interpolação -->
<p>O valor selecionado é {{ selectedNum }}</p>
```
```ts
// ...
export class AppComponent {
// declaramos um valor inicial/padrão do selectedNum,porque ele sempre vai começar com o primeiro option pré selecionado
selectedNum = "1";
// agora passamos para a função selectedValue o num que será do tipo HTMLInputElement
selectedValue(num: HTMLInputElement) {
// mudamos o valor do selectedNum pelo valor selecionado com num.value
this.selectedNum = num.value;
}
// ...
}
```
---
# Alguns Comandos angular-cli
[Documentação](https://angular.io/cli)
## Build
```bash
ng build
```
- default dev : sem minificação
- `--prod`: minificado
irá gerar o folder _dist_ com os arquivos do **build**.
!dica: lib npm **http-server** para rodar a aplicação.
## Verificar lint
```bash
ng lint
```
## Teste unitário
```bash
ng test
```
### Teste end-to-end com Protractor
```bash
ng e2e
```
## Modificar estilo de um projeto existente
**!Modifica apenas os próximos componentes, os já existentes continuarão com as extensões selecionadas anteriormente. Para modificar, será necessário mudar as extensões manualmente nos arquivos.**
```bash
ng set defaults.styleExt <estilo>
```
Estilo:
- `scss` para sass
- `less` para less
- `styl` para stylus
---
# Diretivas
> Angular 2 categoriza diretivas em 3 partes:
>
> 1. Diretivas com modelos conhecidos como Componentes
> 2. Diretivas que criam e destroem elementos DOM conhecidos como **Diretivas Estruturais**
> 3. Diretivas que manipulam o DOM alterando o comportamento e a aparência conhecidas como **Diretivas de Atributo**
> --[codementor.io](https://www.codementor.io/christiannwamba/build-custom-directives-in-angular-2-jlqrk7dpw)
## Diretivas Estruturais
> Diretivas estruturais são responsáveis pelo layout HTML. Eles moldam ou reformulam a estrutura do DOM, geralmente adicionando, removendo ou manipulando elementos. --[Angular Guide](https://angular.io/guide/structural-directives#what-are-structural-directives)
### ngFor
```
*ngFor="expression"
```
Exemplo:
Considere um array de números declarados no arquivo **example.component.ts**,
`arr = [1, 2, 3];`:
```html
<ul>
<li *ngFor="let num of arr">{{ num }}</li></li>
</ul>
```
Neste caso, será gerado um `<li>` para cada número do array.
Resultado:
- 1
- 2
- 3
### ngIf
```
*ngIf="expression"
```
Exemplo:
Considere este select de **example.component.html**:
```html
<select #num (change)="selectedValue(num)">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<p *ngIf="selectedNum <= '2'">O valor selecionado é {{ selectedNum }}</p>
```
Neste caso, será feita a validação da expressão: `selectedNum <= '2'` e a tag `<p>` só será exibida caso a validação seja positiva (1 e 2).
### ngElse
TODO
### ngSwitch
O ngSwitch funciona como o switch que utilizamos no js comum.
Só para relembrarmos como é o switch no js:
```js
switch (expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
```
Exemplo:
ao clicarmos nos botões abaixo queremos exibir uma mensagem de acordo com o botão
```html
<!-- ao clicarmos atribuimos o valor a variavel msg -->
<button type="button" class="btn btn-primary" (click)="msg = 'warning'">
ok
</button>
<button type="button" class="btn btn-success" (click)="msg = 'success'">
Success
</button>
<button type="button" class="btn btn-danger" (click)="msg = 'danger'">
Danger
</button>
<button type="button" class="btn btn-warning" (click)="msg = 'warning'">
Warning
</button>
<!-- aqui estão as mensagens. Fazemos a verificação: -->
<!-- [ngSwitch]="msg" -->
<div class="container" [ngSwitch]="msg">
<!-- ngSwitchDefault: msg padrão -->
<p *ngSwitchDefault>Clique em um botão</p>
<!-- caso a msg = ok exibimos esse parágrafo -->
<p *ngSwitchCase="'ok'">OK! :D</p>
<!-- caso a msg = success exibimos esse parágrafo, etc -->
<p *ngSwitchCase="'success'">Sucesso! :)</p>
<p *ngSwitchCase="'danger'">Perigo! :z</p>
<p *ngSwitchCase="'warning'">Atenção! 8/</p>
</div>
```
## Diretivas de atributo
### ngClass
> É usado para adicionar e remover classes CSS em um elemento HTML. Podemos vincular várias classes CSS ao NgClass simultaneamente, que podem ser adicionadas ou removidas. Existem diferentes maneiras de vincular classes CSS a NgClass que estão usando string, array e objeto. --[Concrete Page](https://www.concretepage.com/angular-2/angular-2-ngclass-example)
Aplica uma classe CSS.
Ao utilizar '-' deve-se estar entre aspas simples (ex: 'background-color') ou utilizar CamelCase (ex: **backgroundColor**)
```html
[ngClass]="{'classe-css': expression}"
<!-- varias -->
[ngClass]="{ 'classe-css': expression, 'classe-css': expression, 'classe-css':
expression }"
```
Exemplo:
```html
<ul *ngFor="let fruit of fruits">
<li
[ngClass]="{
'text-red': fruit.name === 'apple',
'text-yellow': fruit.name === 'banana',
'text-orange': fruit.name === 'orange'
}"
>
{{ fruit.name }}
</li>
</ul>
```
#### Sintaxe alternativa para ngClass
```html
[class.prop]="value"
```
### ngStyle
Aplica uma propriedade CSS.
Ao utilizar '-' deve-se estar entre aspas simples (ex: 'background-color') ou utilizar CamelCase (ex: **backgroundColor**)
```
[ngStyle]="{propCSS: expression}"
<!-- em casos que se usam unidades: -->
[ngStyle]={'propCSS.unit': value}
```
Exemplos:
```html
<!-- simples, atribui a cor azul ao background-color deste elemento -->
<p [ngStyle]="{ backgroundColor: 'blue' }">{{ person.age }}</p>
<!-- com expressão -->
<p [ngStyle]="{ backgroundColor: person.age > 18 ? 'green' : 'yellow' }"></p>
<!-- com unidade em -->
<p [ngStyle]="{ 'fontSize.em': 2.5}">{{ person.age }}}</p>
```
#### Sintaxe alternativa ngStyle
```html
[style.<property
>]=""
<!-- em casos que se usam unidades: -->
[style.<property>.<unit>]=""</unit></property></property
>
```
Exemplo:
```
[style.color]="green"
<!-- para aplicar uma font-size de 16px -->
[style.font-size.px]="16"
```
## Diretivas customizadas
TODO
```bash
ng g d dir/directive-name
```
geralmente criamos no dir **shared**.
Será gerado um arquivo **directive-name.directive.ts**
```ts
// importar o ElementRef e o Renderer
import { Directive, ElementRef, Renderer } from "@angular/core";
@Directive({
// este nome do seletor deverá ser utilizado na tag html que receberá a diretiva
selector: "[appDiretivaExample]"
// para restringir a tag a que esse diretiva poder ser aplicada, basta adicionar o nome da tag 'nome-da-tag[nomeDiretiva]', inclusive para tag componentes
// selector: 'button[appDiretivaExample]'
})
export class DiretivaExampleDirective {
// geralmente utilizamos a inicial _ na nomeação para indicar que é uma variável privada
constructor(private _elementRef: ElementRef, private _renderer: Renderer) {
// aplicamos as modificações
this._renderer.setElementStyle(
this._elementRef.nativeElement,
"background-color",
"red"
);
// este console.log mostra os atributos que podem ser modificados
// console.log(this._elementRef);
// Boas práticas: o uso do ElementRef, para modificação direta do DOM, não é recomendado por questoes de vulnerabilidade da aplicação. Assim, é recomendado utilizar o Renderer
// this._elementRef.nativeElement.style.backgroundColor = 'green';
}
}
```
para aplicar a diretiva customizada na tag:
```html
<h1>Diretiva Customizada</h1>
<button appDiretivaExample>Exemplo</button>
```
## HostListener
Permite ouvir eventos no elemento ou componente hospedeiro (host).
Neste exemplo, mudamos o tamanho da fonte quando passamos o mouse sobre o texto
```ts
// importa HostListener
import { Directive, ElementRef, Renderer, HostListener } from "@angular/core";
@Directive({
// este nome do seletor deverá ser utilizado na tag html que receberá a diretiva
selector: "[appHighlightMouse]"
})
export class HighlightMouseDirective {
// @HostListener('nomedoevento') função() {}
@HostListener("mouseenter") onMouseEnter() {
this._renderer.setElementStyle(
this._elementRef.nativeElement,
"font-size",
"2em"
);
}
@HostListener("mouseleave") onMouseLeave() {
this._renderer.setElementStyle(
this._elementRef.nativeElement,
"font-size",
"1em"
);
}
constructor(private _elementRef: ElementRef, private _renderer: Renderer) {}
}
```
## HostBinding
Permite definir propriedades no elemento ou componente hospedeiro (host) da diretiva por meio de uma variável.
Este exemplo faz o mesmo que o demonstrado em HostListener, porém de uma maneira otimizada utilizando o HostBinding.
HostingListener + HostBinding:
```ts
// importa HostBinding
import {
Directive,
ElementRef,
Renderer,
HostListener,
HostBinding
} from "@angular/core";
@Directive({
selector: "[appHighlightMouse]"
})
export class HighlightMouseDirective {
@HostListener("mouseenter") onMouseEnter() {
// utilizando HostBinding
this.changeSize = "2em";
// método anterior
// this._renderer.setElementStyle(
// this._elementRef.nativeElement,
// 'font-size',
// '2em'
// )
}
@HostListener("mouseleave") onMouseLeave() {
// utilizando HostBinding
this.changeSize = "1em";
// método anterior
// this._renderer.setElementStyle(
// this._elementRef.nativeElement,
// 'font-size',
// '1em'
// )
}
// @HostBinding('style.cssAtributeName') varName: type;
@HostBinding("style.fontSize") changeSize: string;
constructor() // private _elementRef: ElementRef,
// private _renderer: Renderer
{}
}
```
---
# Operador Elvis (?)
Exemplo:
```html
<!-- elvis -->
<h1>{{ person?.name }}</h1>
<!-- é o mesmo que -->
<h1>{{ person != null ? person.name : '' }}</h1>
```
# Model
TODO
---
# Services
> _Service_ é uma categoria abrangente que inclui qualquer valor, função ou recurso de que um aplicativo precisa. Um serviço é tipicamente uma classe com um propósito estreito e bem definido. Deve fazer algo específico e fazê-lo bem.
> Angular distingue componentes de serviços para aumentar a modularidade e a reutilização.
> Ao separar a funcionalidade relacionada à visualização de um componente de outros tipos de processamento, você pode tornar suas classes de componentes simples e eficientes.
> Idealmente, o trabalho de um componente é permitir a experiência do usuário e nada mais. Um componente deve apresentar propriedades e métodos para vinculação de dados, a fim de mediar entre a visualização (renderizada pelo modelo) e a lógica do aplicativo (que geralmente inclui alguma noção de um modelo).
> Um componente pode delegar determinadas tarefas aos serviços, como buscar dados do servidor, validar a entrada do usuário ou registrar-se diretamente no console. Ao definir essas tarefas de processamento em uma classe de serviço injetável, você torna essas tarefas disponíveis para qualquer componente. Você também pode tornar seu aplicativo mais adaptável injetando diferentes provedores do mesmo tipo de serviço, conforme apropriado em diferentes circunstâncias. --[angular.io](https://angular.io/guide/architecture-services)
```bash
ng g service <name>
```
- DRY
- Manutenção
- Facilidade para migrar para outras tecnologias
Os _services_ geralmente são classes que reunem os métodos para serem utilizados pelos componentes.
Assim:
-> Componente: interação usuário
-> Serviço: cérebro, lógica do negócio, classes utilitárias.
Exemplo:
TODO
## Injeção de dependências
TODO
---
# Rotas
TODO
**app.component.html**:
add a tag router-outlet onde será renderizado o componente de rota
```html
<router-outlet></router-outlet>
```
**app-routing.module.ts**:
```ts
import { NgModule } from "@angular/core";
// importar Routes e RoutersModule
import { Routes, RouterModule } from "@angular/router";
// importar ModuleWithProviders
import { ModuleWithProviders } from '@angular/core';
// importar componentes
import { LoginComponent } from "./login/login.component";
import { HomeComponent } from "./home/home.component";
// add path e o nome dos componentes
// que seriam o caminho/endereço e o componente que deverá ser renderizado para esse caminho
const routes: Routes = [
// um caminho default
{ path: "", pathMatch: "full", redirectTo: "login" }
// outras rotas
{ path: "login", component: LoginComponent },
{ path: "home", component: HomeComponent }
];
// para rotas principais
export const routing: ModuleWithProviders = RouterModule.forRoot(APP_ROUTES);
// rotas de funcionalidade usar forChild (ex: recipes-detail)
// export const routing: ModuleWithProviders = RouterModule.forChild(APP_ROUTES);
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
```
no arquivo **app.module.ts**:
```ts
// importar o arquivo de rotas
import { routing } from './app.routing';
// ...
// add aos imports
@NgModule({
// ...
imports: [
// ...
routing
],
providers: [],
bootstrap: [AppComponent]
})
```
## Adicionar link de rota (routerLink)
adicionar o `routerLink` com o caminho que foi criado no arquivo de rotas.
```html
<a routerLink="/path">path</a>
<!-- exemplo -->
<a routerLink="/login">Login</a>
```
---
## Rota com parâmetros
- obter o parâmetro
- subscribe
- unsubscribe
o que vai mudar de um caso para o outro é o conteúdo de exemplo do arquivo **welcome-page.component.ts**.
**app-routing.module.ts**:
```ts
// ...
import { WelcomeComponent } from "./welcome/welcome.component";
// ...
// rota com parâmetro rota/:parametro
{ path: "home/:welcome", component: WelcomeComponent }
// ...
```
no **home.component.html**:
```html
<!-- exemplo -->
<input #name />
<a [routerLink]="['welcome', name.value]">Boas vindas</a>
```
Para exibir um valor na tela, supondo que temos um input onde o usuário digita seu nome na página home (**home.component.html**):
**welcome-page.component.html:**
```html
<h2>Olá, {{ name }}, seja bem vinda (o)!</h2>
```
### Obter parâmetro
**welcome-page.component.ts:**
```ts
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
@Component({
selector: "app-welcome-page",
templateUrl: "./welcome-page.component.html",
styleUrls: ["./welcome-page.component.css"]
})
export class WelcomePage implements OnInit {
name: string;
constructor(private route: ActivatedRoute) {
console.log(this.route.snapshot.params["name"]);
this.id = this.route.snapshot.params["name"];
}
ngOnInit() {}
}
```
### Subscribe e unsubscribe
**welcome-page.component.ts:**
```ts
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
// add import do Subscription
import { Subscription } from "rxjs";
@Component({
selector: "app-welcome-page",
templateUrl: "./welcome-page.component.html",
styleUrls: ["./welcome-page.component.css"]
})
export class WelcomePage implements OnInit {
name: string;
// add uma variável do tipo Subscription
subscription: Subscription;
constructor(private route: ActivatedRoute) {}
// subscribe
ngOnInit() {
this.subscription = this.route.params.subscribe((params: any) => {
this.name = params["name"];
});
}
// unsubscribe
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
```
# Rotas imperativas
TODO
```ts
import { ActivatedRoute, Router } from "@angular/router";
// exemplo, faz a validação do dado e redireciona para outra página
if (this.name == null) {
this.router.navigate(["/error"]);
}
```
_!não esquecer que todos os caminhos devem estar declarados no aquivo de rotas._
## Definir parâmetro de url (query)
Exemplo:
```html
<!-- !nota: 'notebook' está entre aspas simples, porque é uma string -->
<button routerLink="/produtos" [queryParams]="{prod:'notebook'}">
Produtos
</button>
<button routerLink="/produtos" [queryParams]="{pagina:21}">Produtos</button>
```
Assim, quando clicado neste botão, irá acrescentar os parâmetros solicitados na url da página:
_http://localhost:4200/produtos?pagina=notebook_
## Extrair parâmetro da url
Exemplo:
Um botão que ao ser clicado muda para a próxima página.
```html
<button (click)="nextPage()">Próxima página</button>
```
em **produtos.components.ts**:
```ts
// acrescentar os imports necessários
import { Subscription } from "rxjs";
import { ActivatedRoute, Router } from "@angular/router";
@Component({
selector: "app-produtos",
templateUrl: "./produtos.component.html",
styleUrls: ["./produtos.component.css"]
})
export class produtosComponent implements OnInit {
page: number;
subscription: Subscription;
constructor(private activatedRoute: ActivatedRoute, private router: Router) {}
ngOnInit() {
this.subscription = this.activatedRoute.queryParams.subscribe(
(queryParams: any) => {
this.page = queryParams["page"];
}
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
nextPg() {
// a expressão abaixo muda a url para outro caminho utilizando a classe Router no @angular/router
// e vai somando 1 à página a cada vez que o botão é clicado
// http://localhost:4200/produtos?page=2
this.router.navigate(["/produtos"], { queryParams: { page: ++this.page } });
}
}
```
# Forms: Template Driven e Data Driven
**!não esquecer de importar o FormsModule no módulo**:
```ts
import { FormsModule } from "@angular/forms";
```
- Template Driven:
- **orientado a template**
- criação, configuração e validação no HTML (template)
- FormGroup criado pelo Angular do HTML
- form submetido através do `ngSubmit`
- Data Driven (Reativos)
- **orientado a dados**
- você programa o formulário e sincroniza com o DOM. A manipulação é feita via código no component.
- criação, configuração e validação no componente
- FormGroup no componente
- não é necessário ngSubmit
## Template Driven
TODO ex msg de erro
TODO serValue
TODO patch value
TODO HTTP Post
Exemplo:
no arquivo **template-drive.component.html**
```html
<!-- criar var (ex #myForm) para referenciar o formulário -->
<!-- ngForm: angular passa a ajudar a gerenciar -->
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<div class="form-group">
<label for="nome">Nome</label>
<!-- acrescentar ngModel e um name para associação -->
<input
type="text"
class="form-control"
id="nome"
name="nome"
placeholder="Nome"
ngModel
/>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
class="form-control"
id="email"
name="email"
placeholder="nome@email.com"
ngModel
/>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
```
no arquivo **template-drive.component.ts**
```ts
import { Component, OnInit } from "@angular/core";
@Component({
selector: "app-template-form",
templateUrl: "./template-form.component.html",
styleUrls: ["./template-form.component.css"]
})
export class TemplateFormComponent implements OnInit {
user: any = {
name: "Lays",
email: "lays@lays.com"
};
onSubmit(form) {
// retorna os valores associados através da referência name e ngModel
console.log(form.value);
// ou
console.log(this.user);
}
constructor() {}
ngOnInit() {}
}
```
## Data Driven: Formulários reativos
no _module.ts_:
- importar o **ReactiveFormsModule**
- adicionar aos imports
no _component.ts_, importar a classe:
- Importar as classes FormGroup e FormControl (ou FormBuilder)
- criar uma variável do tipo FormGroup
<!-- TODO add content, verify examples -->
arquivo **app.module.ts** (ou no módulo que for utilizar):
```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
// importar ReactiveFormsModule
import { ReactiveFormsModule } from "@angular/forms";
// ...
@NgModule({
// ...
imports: [
// ...
// add nos imports
ReactiveFormsModule
]
//...
})
export class AppModule {}
```
**reactive-form.component.ts**:
```ts
import { Component, OnInit } from "@angular/core";
// Importar a classe FormGroup e FormControl/FormBuilder
import { FormGroup, FormControl } from "@angular/forms";
@Component({
selector: "app-data-form",
templateUrl: "./data-form.component.html",
styleUrls: ["./data-form.component.css"]
})
export class DataFormComponent implements OnInit {
// declarar uma variável do tipo FormGroup
form: FormGroup;
// maneira com FormBuilder
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.form = this.formBuilder.group({
name: ["Valor inicial nome"],
email: ["Valor inicial email"]
});
}
// ou
// com new FormControl
// constructor() { }
// ngOnInit() {
// this.form = new FormGroup({
// name: new FormControl('Valor Nome Inicial'),
// email: new FormControl('Valor Email Inicial'),
// });
// }
}
```
no html:
```html
<!-- add a diretiva [formGroup]="variable name" para linkar com a variável que está no componente -->
<!-- add (ngSubmit)="onSubmit() vinculado ao component.ts -->
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<!-- ... -->
<!-- add formControlName para linkar e atualizar o valor das variáveis do formBuilder de acordo com o input -->
<input formControlName="email" />
<!-- ... -->
</form>
```
## Forms validation
[Validation Angular.io](https://angular.io/guide/form-validation)
Nessa abordagem de formulário reativo, controlamos os forms pelo componente e não pelo template (DOM), por isso ao invés de simplesmente colocar um atributo `required` na tag HTML, fazemos isto através de código no componente.
Exemplo utilizando o Validators do @angular/forms:
- importar a classe Validators
- fazer as validações através do FormControl
- `new FormControl(defaultValueOfTheInput, Validators)`, se for mais de um tipo de validação, utilizar array: `new FormControl(null, [Validators.required, Validators.email])`
_app.component.ts_:
```ts
// importar a classe Validators
import { FormGroup, FormControl, Validators } from '@angular/forms';
// ...
ngOnInit() {
// add validações ao FormGroup
this.signupForm = new FormGroup({
'username': new FormControl(null, Validators.required),
'email': new FormControl(null, [Validators.required, Validators.email]),
'gender': new FormControl('female')
});
}
```
Podemos exibir mensagens adicionais no HTML para informar o usuário. Exemplo, um `input` de email:
```html
<div class="form-group">
<label for="email">email</label>
<input type="text" id="email" class="form-control" formControlName="email" />
<!-- utilizando ngIf -->
<span
*ngIf="!signupForm.get('email').valid && signupForm.get('email').touched"
class="help-block"
>Dado Inválido</span
>
</div>
```
### Custom Validation
Suponha um input, onde o usuário digita o nome de um produto, e queremos validar, se este produto está na lista de produtos que acabaram.
```ts
import { Component, OnInit } from "@angular/core";
// Importar as classes
import {
FormGroup,
FormControl,
Validators,
FormArray,
FormBuilder
} from "@angular/forms";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
invalidProducts = ["notebook", "mouse"];
constructor(private formbuilder: FormBuilder) {}
ngOnInit() {
this.signupForm = new FormGroup({
product: new FormControl(null, [
Validators.required,
this.invalidProducts.bind(this)
])
});
}
onSubmit() {}
// custom validator
invalidProduct(control: FormControl): { [s: string]: boolean } {
if (this.invalidProducts.indexOf(control.value) != -1) {
return { productIsInvalid: true };
}
return null;
}
}
```
### Status Change
!Nota: para saber mais sobre este e outros FormControls, acesse [angular.io](https://angular.io/api/forms/FormControl).
```ts
this.signupForm.statusChanges.subscribe(status => console.log(status));
```
- Pending
- Valid
- Invalid
### Value Change
```ts
this.signupForm.valueChanges.subscribe(value => console.log(value));
```
### Reset Values
Podemos limpar todos os dados digitados no campo de input após clicar em submit, por exemplo:
```ts
onSubmit() {
this.signupForm.reset();
}
```
Neste caso acima o método `reset()` irá apagar o valor de todos os campos. É configurar para apagar campos específicos,
Exemplo, voltar o botão para o valor inicial de Enviar e desabilitado:
```ts
control.reset({ value: "Enviar", disabled: true });
```
### SetValue
É possível atribuir um valor padrão de preenchimento de um campo de input com `setValue`, por exemplo:
```ts
this.signupForm.setValue({
email: "test@test.com"
});
```
Com isso, o campo de input já virá previamente preenchido com email **test@test.com**, ainda será possível editá-lo.
### Modificar/corrigir valor de input com PatchValue
Vamos supor que você queira modificar o input de email:
```ts
this.signupForm.patchValue({
email: "seu-email@test.com"
});
```
---
# Pipes (filtros)
<!-- TODO improvements -->
```html
<!-- {{ ... | pipe }} -->
<tag> {{ data | pipe }} </tag>
<!-- {{ ... | pipe:adicionais }} -->
<tag>{{ data | pipe: }}</tag>
```
- [Guia Pipes](https://angular.io/guide/pipes)
- [Pipes list](https://angular.io/api?query=pipe)
- [Pipe Lib](https://github.com/fknop/angular-pipes)
Os pipes são utilizados para transformar/filtrar valores no template.
- pura: não observa modificações no objeto
- impura: observa modificações no objeto
Suponha um objeto product. Exemplo:
```html
<!-- exibe o nome do produto em Uppercase (capitalizado) -->
<h1>{{ product.name | uppercase }}</h1>
<ul>
<!-- exibe a quantidade no formato 00.00 -->
<!-- onde (numero de casas antes da vírgula.minimoCasas-MaxCasas depois da vírgula -->
<li>Quantidade: {{ product.amount | number: '2.2-2'}}</li>
<!-- exibe o preço do produto no formato R$ 00.00 -->
<li>Preço: {{ product.price | currency: 'BRL':true }}</li>
<!-- exibe a data no formato dia-mes-ano -->
<li>Validade: {{ product.date | date:'dd-MMM-yyyy' }}</li>
<!-- exibe a composição do produto em formato JSON -->
<li>Composição: {{ product.comp | JSON }}</li>
</ul>
```
## Criar pipe customizado
```bash
ng g pipe
# ou
ng g p
```
**!não esquecer de importar no módulo a pipe criada e adicionar nas _declarations_.**
!o padrão é pure, para modificar este comportamento, é necessário modificar no arquivo de **pipe.ts**:
```ts
// ...
@Pipe({
// add este metadado pure: false
pure: false
})
```
### Formato Local
Para modificar as configurações do projeto quanto a exibição de alguns dados filtrados pelo pipe:
exemplo, para exibição no formato brasileiro (ao invés de 1.99 ser 1,99):
no module.ts:
```ts
providers: [
{
provide: LOCALE_ID,
useValue: "pt-BR"
// useClass: '',
// useFactory: ''
}
];
```
## Observables
= Data source (user imput, http requests, etc)
Transferência de dados assíncrona.
Observer:
- Handle Data
- Handle Errors
- Handle Competition
---
# Style Guide
<!-- TODO add content research -->
## Imports
```ts
imports do angular
// pula uma linha
outros imports (componentes, etc)
```
---
## Importar JSON
1. Criar arquivo **json-typings.d.ts** na pasta *app* e adicionar o código:
```ts
declare module "*.json" {
const value: any;
export default value;
}
```
2. No arquivo **component.ts** importar o JSON, exemplo:
```ts
import * as data from './data.json';
```
!Nota: data, irá importar o módulo todo. Para acessar os dados do json em si, será necessário acessar o *default* do módulo: `data.default`.
3. Atribuir valor a uma variável para utilizar no código, exemplo:
```ts
users = data.default;
```