sábado, 1 de dezembro de 2018

Resumo sobre Angular 4+

Como estamos sempre lidando com muitas tecnologias diferentes, cada uma delas cheia de particularidades, as vezes faço um resumo para não perder muito tempo procurando o básico. Esse é meu resumo pessoal sobre o Angular 4.

NPM

- npm install nome_da_biblioteca --save
- npm uninstall nome_da_biblioteca --save

Angular-Cli

- ng new nome_do_projeto => cria um projeto,  inclusive a pasta raiz.
- ng init => quando já existir a pasta raiz e quiser criar a estrutura do projeto (deve ser executado no diretório).
- ng serve => executa o projeto.
- ng g c nome-do-componente => cria o componente.
- ng g d nome-da-diretiva => cria uma diretiva.
- ng g s nome-do-servico => cria o serviço.
- ng g m nome-do-model => cria o módulo.
- ng g m nome-do-model --routing => cria o módulo e o módulo de rotas
- ng g g nome-do-guarda => cria um guarda de rotas
- ng g p nome-do-pipe => cria o pipe.
- ng lint => lista erros de javascript e anti-padrões do style guide do Angular

Componentes

- interpolação => {{variavel}}
- propert-binding => [propriedade]="variavel" => <input [value]="nome" />
- event-binding => (evento)="método" => (click)="salvar($event.target.value)"
- two-way-data-binding => [(ngModel)]="nome"

- comunicação do componente pai para o filho:

@Input() variavel: tipo;

- comunicação do componente filho para o pai:

@Output variavel_evento = new EventEmitter();

//em algum momento dentro de um método usa-se:
this.variavel_evento.emit(objeto_ou_valor);

Variável de referência

usa-se o '#' antes de um nome => #imputName => <input type="text" class="form-control" #imputName />

-então essa variável fica disponível em todo o template(componente.html), mas não no componente(componente.ts).

Para ser acessada no componente, tem duas formas:

-pode ser acessada através do decorator @ViewChild('nome_da_variavel')

@ViewChild('imputName') campo: ElementRef;
//para usar depois basta fazer:
//this.campo.nativeElement.value;

-pode ser passada para o componente através de um event:

<button type="button" class="btn btn-primary"
        (click)="adicionar(imputName.value)">Adicionar</button>
// valor será recebido no método adicionar(valor) do componente.ts.

Ciclo de vida:

- construtor
- ngOnChanges => disparado sempre quando o valor do property-binding é atualizado.
- ngOnInit => Quando o componente é inicializado.
- ngDoCheck => A cada ciclo de verificação de mudanças.
- ngAfterContentInit => depois de inserir conteúdo externo na view
- ngAfterContentChecked => a cada verificação de conteúdo inserido
- ngAfterViewInit => depois que o angular inicializa os componentes views e views filhas.
- ngAfterViewChecked => após a checagem dos componentes views e views filhas.
- ngOnDestroy => antes da destruição do componente.

Diretivas

- diretivas de componentes => diretivas dos nossos componentes => <meu-componente></meu-componente>
- diretivas estruturais => vem precedida de * (asterísco) => *ngFor, *ngIf, *ngSwitch, etc.
- diretivas de atributos => interagem com o elemento que foram aplicadas => ngStyle, ngClass, etc.

Ouvindo eventos do hopedeiro da diretiva e acessando atributos HTML:
-  Exemplo de como ouvir eventos:

  @HostListener('mouseover') onMouseOver(){
    this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'blue');
  }

  @HostListener('mouseout') onMouseOut(){
    this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'red');
  }

  constructor(private elementRef: ElementRef, private renderer: Renderer2 ) {

  }

- Exemplo de como acessar atributos:

@HostBinding('style.backgroundColor') backgroundColor: string;

Dessa forma, o @HostEvent não precisaria usar o rendered2 nem o elementRef e ficaria assim:

@HostListener('mouseover') onMouseOver(){
    this.backgroundColor = 'blue';
}

Pode-se usar o @input() para receber valores de quem for usar o componente com a diretiva criada.

Exportar a diretiva:
- As diretivas podem ser exportadas e terem seus métodos expostos da seguinte forma:

@Directive({
  selector: '[nome_do_seletor_da_diretiva]',
  exportAs: 'nome_da_diretiva'
})

- Isso possibilita que sejam usados de outras formas, veja como pegar a diretiva e usar seus métodos:

<input type="text" class="form-control" [(ngModel)]="nome"
        (focus)="adicionado = false" nome_do_seletor_da_diretiva
        #campo="nome_da_diretiva">

<button class="btn btn-info" (click)="campo.metodo_da_diretiva()">Clique-me</button>


NG-CONTENT
- Permite passar conteúdo (incluindo outros componentes) para um componente. Observe o uso do seletor e da classe para que isso funcione.
- Se eu tiver um componente chamado exemplo-ng-content.component.html com o seguinte conteúdo:

<div class="panel panel-default">
  <div class="panel-heading">
    <ng-content select=".titulo"></ng-content>
  </div>
  <div class="panel-body">
    <ng-content select=".corpo"></ng-content>
  </div>
</div>

pode ser usado em outro componente desta forma:

<app-exemplo-ng-content>
    <div class="titulo">Título do Painel</div>
    <div class="corpo">
        Conteúdo passado para o componente corpo.
    </div>
    <div class="corpo">
        Conteúdo 2 passado para o componente corpo.
    </div>
</app-exemplo-ng-content>

Form validations

- autocomplete="off" => desabilita autocomplite no formulário
- diretivas do angular:

required, email, minlength="5", maxlength="15", pattern="[a-zA-Z ]*"

- pegar o formulario:

<form #meuForm="ngForm">

- pegar campos do formulário:

<input type="text" #nome="ngModel" name="nome" [(ngModel)]="cliente.nome" />

- validar:

nome.haserror('required') => pode ser usado em um ngIf por exemplo e exibir ou não uma mensagem.

- propriedades interessantes:

nome_do_campo.touched => se o campo foi tocado
nome_do_campo.pristine => se o campo já teve algum valor ou está virgem
nome_do_campo.dirty => se o campo já foi alterado

- estilizando componentes invalidos dos forms com as classes do angular:

input.ng-invalid.ng-touched, select.ng-invalid.ng-touched {
  border: 1px solid red;
}

- binding de class:

<input type="text" #nome="ngModel" name="nome" [(ngModel)]="cliente.nome" [class.nome_da_classe]="propriedade_ou_condicao_boolean"/>

- binding de style:

<input type="text" #nome="ngModel" name="nome" [(ngModel)]="cliente.nome" [style.nome_da_propriedade]="propriedade_ou_condicao_boolean ? 'valor_1' : 'valor_2' "/>

- resetar um formulario:

<form autocomplete="off" #usuarioForm="ngForm"
      (ngSubmit)="salvar(usuarioForm)">

No submit do form estamos chamando o método salvar e passando o próprio form.
Então no componente basta resetarmos o form:

salvar(form: NgForm) {
//faz outras coisas
...
//reseta o formulário
    form.reset();
  }

Serviços

- A anotação @Injectable() permite que o serviço receba injeção de outros serviços.
- Serviços servem para comunicação com servidor.
- Para evitar duplicação de código.
- Lógica da aplicação deve estar nos serviços.
- Classes utilitárias devem ser feitas como serviços.
- Serviços são singletons se forem adicionados dentro de qualquer módulo na propriedade "providers: []" do decorator @NgModule. O que permite compartilhar recursos entre componentes naturalmente (listas, variáveis, etc).
- Caso sejam adicionados na propriedade "providers: []" do componente, serão uma instância para cada componente e componentes filhos, o que já impede esse compartilhamento global.
- Uma vez criadas instâncias separadas por componentes, a comunicação entre eles só pode ser feita através do EventEmitter e se o EventEmitter for uma propriedade estática.

static variavel_evento = new EventEmitter();

//dentro de algum método
this.variavel_evento.emit( objeto_ou_valor );

- Quem for escutar o evento deve fazer da seguinte forma:

// no contrutor recebe o serviço
constructor(private cursosService: CursosService) {}

// no ngOnInit se inscreve como ouvinte
CursosService.criouNovoCurso.subscribe(
      //faz alguma coisa aqui
curso => this.cursos.push(curso)
    );

 - Os services são declarados no provider dos módulos ou componentes como já descrito acima,
da forma abreviada ou extensa.

Abreviada:

@NgModule({
  declarations: [
    AppComponent,
    FuncionarioCardComponent,
    FuncionarioFormComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    FuncionarioService
  ],
  bootstrap: [AppComponent]
})

Extensa

@NgModule({
  declarations: [
    AppComponent,
    FuncionarioCardComponent,
    FuncionarioFormComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    { provide: FuncionarioService, useClass: FuncionarioService, }
  ],
  bootstrap: [AppComponent]
})

Na forma extensa, é possível fornecer um método Factory ao invés de uma classe.
A vantagem é que a factory pode instanciar uma classe com parâmetros se for necessário.

const criarFuncionarioService = () => {
  return new FuncionarioAbreviadoService(param1, param2...);
}

@NgModule({
  declarations: [
    AppComponent,
    FuncionarioCardComponent,
    FuncionarioFormComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    { provide: FuncionarioService, useFactory: criarFuncionarioService }
  ],
  bootstrap: [AppComponent]
})

Rotas

- Cria-se uma constante em um arquivo app.routing.ts ou no app.module.ts que seja
do tipo Routes do pacote "@angular/router". Esse  paths e componentes.
- O Routes é um array de paths e componentes e deve ser preenchido como no
exemplo abaixo:

const  APP_ROUTES: Routes = [
  { path: 'lancamentos', component: LancamentosPesquisaComponent },
  { path: 'lancamentos/novo', component: LancamentosCadastroComponent },
  { path: 'pessoas', component: PessoasPesquisaComponent },
  { path: 'pessoas/novo', component: PessoasCadastroComponent }
]

- Essa constante deve passar para uma constante do tipo ModuleWithProviders do pacote "@angular/core".
- Para isso é preciso usar o RouterModule do "@angular/router". Se essa constante foi criada em um arquivo
separado, ela deve ser exportada. O código fica assim:

export const routing: ModuleWithProviders = RouterModule.forRoot(APP_ROUTES);

- Para usar as rotas coloca-se a diretiva routerLink nos links recebendo o devido path declarado na constante
que no exemplo chamei de APP_ROUTES.

<li class="navbar-menuitem"><a routerLink="lancamentos">Lançamentos</a></li>

- Para as rotas funcionarem, em cada módulo é necessário importar o RouterModule do '@angular/router'.

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
    BrowserModule,
    RouterModule
  ],
  providers: [
    ...
  ],
  bootstrap: [AppComponent]
})

- Para destacar rotas ativas, basta usar a diretiva routerLinkActive passando o nome da classe CSS que contém o estilo desejado.

<li class="navbar-menuitem" routerLinkActive="ativo"><a routerLink="lancamentos">Lançamentos</a></li>

- Para carregar rotas de forma lazying, dependendo da versão, pode-se usar uma dessas formas:

{ path: 'cursos', loadChildren: 'app/cursos/cursos.module#CursosModule'}  versão 2+

{ path: 'cursos', loadChildren: './cursos/cursos.module#CursosModule'}  versão 7+

{ path: 'cursos', loadChildren: () => import('./cursos/cursos.module').then(m => m.CursosModule)} versão 9+

Events

(focus)="myMethod()"  // An element has received focus
(blur)="myMethod()"   // An element has lost focus

(submit)="myMethod()"  // A submit button has been pressed

(change)="myMethod()"

(scroll)="myMethod()"

(cut)="myMethod()"
(copy)="myMethod()"
(paste)="myMethod()"

(keydown)="myMethod()"
(keypress)="myMethod()"
(keyup)="myMethod()"

(mouseenter)="myMethod()"
(mousedown)="myMethod()"
(mouseup)="myMethod()"

(click)="myMethod()"
(dblclick)="myMethod()"

(drag)="myMethod()"
(dragover)="myMethod()"
(drop)="myMethod()"








Nenhum comentário:

Postar um comentário