Angular 2 - Cadastro de Clientes - XIV
Neste artigo vou mostrar como criar um cadastro de clientes e fazer o CRUD usando o Angular 2 e o Visual Studio Code. |
Neste artigo vou continuar com a validação mostrando as mensagens de erro usando BootStrap e ngClass. (link do artigo anterior)
Neste momento vamos usar os recursos do BootStrap para exibir mensagens ao usuário.
Veja a documentação da validação de formulários neste link: https://v4-alpha.getbootstrap.com/components/forms/#validation (estou usando a versão 4)
Tomando um exemplo da documentação:
<div class="form-group has-success">
<label class="form-control-label" for="inputSuccess1">Input with success</label>
<input type="text" class="form-control form-control-success" id="inputSuccess1">
<div class="form-control-feedback">Success! You've done it.</div>
<small class="form-text text-muted">Example help text that remains unchanged.</small>
</div>
Vemos que o Bootstrap aplica uma classe ao div container do form-group, ao <Label> e ao <input type>. Vamos usar esses recursos em nosso formulário.
No Angular 2 os dois objetos fundamentais do formulário são :
Para iniciar vamos remover o estilo definido no arquivo cliente-detalhe.component.ts.
Abra este arquivo e remova o código definido para o estilo conforme abaixo:
styles: [`
.ng-valid[required] {
border: 2px
solid blue;
}
.ng-invalid:not(form) {
border: 2px
solid red;
}
`]
Após isso, o código deste arquivo deverá ficar assim:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params} from '@angular/router';
import { Location } from '@angular/common';
import { Cliente } from './cliente.model';
import { ClienteService } from './cliente.service';
@Component({
moduleId: module.id,
selector : 'cliente-detalhe',
templateUrl : 'cliente-detalhe.component.html',
})
export class ClienteDetalheComponent implements OnInit {
cliente : Cliente;
constructor(
private clienteService : ClienteService,
private route : ActivatedRoute,
private location : Location
) {}
ngOnInit(): void {
this.cliente = new Cliente(0,'','','',);
this.route.params.forEach((params: Params)=>{
let id: number = +params['id'];
if(id){
this.clienteService.getCliente(id)
.then((cliente: Cliente)=> {
console.log(cliente);
this.cliente = cliente;
});
}
});
}
}
|
Vamos agora abrir o template html e aplicar os recursos do bootstrap de forma estática apenas no campo nome para vermos como funciona.
Abra o arquivo cliente-detalhe.component.html e inclua o código destacado em azul:
<div class="container">
<h2>Salvar Cliente</h2>
<form #clienteForm="ngForm">
<div class="form-group has-danger">
<label for="nome" class="form-control-label">Nome</label>
<input type="text" class="form-control form-control-danger" placeholder="Informe o nome"
required
name="nome"
[(ngModel)]="cliente.nome" >
<div class="form-control-feedback">O campo deve ser informado</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" placeholder="Informe o email"
required
name="email"
[(ngModel)]="cliente.email" >
</div>
<div class="form-group">
<label for="telefone">Telefone</label>
<input type="text" class="form-control" placeholder="Informe o telefone"
required
name="telefone"
[(ngModel)]="cliente.telefone" >
</div>
<button type="submit" class="btn btn-success" [disabled]="!clienteForm.form.valid">Salvar</button>
<a class="btn btn-secondary" routerLink="/">Voltar </a>
</form>
</div>
|
Ao salvar as alterações veremos o resultado no navegador conforme abaixo:
Como podemos ver, os estilos do boostrap aplicados de forma estática funcionam bem, mas imagine fazer esse trabalho para um formulário com muitos campos...
É aqui que entram a diretiva ngClass e o NgModel do Angular. A diretiva ngClass adiciona e remove classes CSS a um elemento HTML.
As classes CSS são atualizadas conforme abaixo, dependendo do tipo de expressão de avaliação :
Já através a diretiva NgModel nos dá acesso aos controles dos campos do formulário. Ela deve ser aplicada na definição do campo, ou seja, no input type.
Nota: Lembre que ngModel não atua apenas fazendo o databinding mas ela atua sobre as classes CSS dos campos dos formulários.
Vamos então aplicar a diretiva ngClass e o NgModel ao nosso template html para exibir mensagens de validação de forma dinâmica.
Abra o arquivo cliente-detalhe.component.html e inclua o código destacado em azul:
<div class="container">
<h2>Salvar Cliente</h2>
<form #clienteForm="ngForm">
<div [ngClass]="{'form-group': true, 'has-danger': (!nome.valid && !nome.pristine) , 'has-success': (nome.valid && !nome.pristine)}">
<label for="nome" class="form-control-label">Nome</label>
<input type="text" class="form-control form-control-danger" placeholder="Informe o nome"
required
#nome="ngModel"
name="nome"
[(ngModel)]="cliente.nome" >
<div class="form-control-feedback" [hidden]="nome.valid || nome.pristine">O campo deve ser informado</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" placeholder="Informe o email"
required
name="email"
[(ngModel)]="cliente.email" >
</div>
<div class="form-group">
<label for="telefone">Telefone</label>
<input type="text" class="form-control" placeholder="Informe o telefone"
required
name="telefone"
[(ngModel)]="cliente.telefone" >
</div>
<button type="submit" class="btn btn-success" [disabled]="!clienteForm.form.valid">Salvar</button>
<a class="btn btn-secondary" routerLink="/">Voltar </a>
</form>
</div>
|
Vamos entender o código:
- #nome="ngModel" : No input type, definimos o NgModel atribuindo-o a uma variável nome, que é o nome do campo, e assim teremos acesso a todos os controles deste campo;
- [hidden]="nome.valid || nome.pristine : Aqui vamos ocultar a mensagem de campo obrigatório quando o campo nome for válido e quando o campo não sofreu nenhuma alteração;
- [ngClass]="{'form-group': true, 'has-danger': (!nome.valid && !nome.pristine) , 'has-success': (nome.valid && !nome.pristine)
Neste código definimos o ngClass usando a notação property binding [ngClass] pois a seguir vamos usar uma expressão Javascript onde vamos definir quais classes de estilo vamos aplicar ao elemento.
Dessa forma aplicamos as seguintes classes :
Abaixo vemos o formulário em dois momentos:
Vemos assim a aplicação dos estilos CSS de forma dinâmica e podemos melhorar ainda mais criando uma classe que vai permitir remover o código do template html e que vai retornar objetos que configuram as classes de estilos que vamos usar.
Abra o arquivo cliente-detalhe.component.ts e inclua o código abaixo em azul :
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params} from '@angular/router';
import { Location } from '@angular/common';
import { Cliente } from './cliente.model';
import { ClienteService } from './cliente.service';
@Component({
moduleId: module.id,
selector : 'cliente-detalhe',
templateUrl : 'cliente-detalhe.component.html',
styles: [`
.ng-valid[required] {
border: 2px solid blue;
}
.ng-invalid:not(form) {
border: 2px solid red;
}
`]
})
export class ClienteDetalheComponent implements OnInit {
cliente : Cliente;
constructor(
private clienteService : ClienteService,
private route : ActivatedRoute,
private location : Location
) {}
ngOnInit(): void {
this.cliente = new Cliente(0,'','','',);
this.route.params.forEach((params: Params)=>{
let id: number = +params['id'];
if(id){
this.clienteService.getCliente(id)
.then((cliente: Cliente)=> {
console.log(cliente);
this.cliente = cliente;
});
}
});
}
getFormGroupClass(isValid : boolean, isPristine: boolean) : {} {
return {
'form-group' : true,
'has-danger': !isValid && !isPristine,
'has-success': isValid && !isPristine
}
}
}
|
Muuito bem, agora basta aplicarmos essa classe ao template html. Abra o arquivo cliente-detalhe.component.html e defina o código destacado em azul a seguir:
<div class="container">
<h2>Salvar Cliente</h2>
<form #clienteForm="ngForm">
<div [ngClass]="getFormGroupClass(nome.valid,nome.pristine)">
<label for="nome" class="form-control-label">Nome</label>
<input type="text" class="form-control form-control-danger" placeholder="Informe o nome"
required
#nome="ngModel"
name="nome"
[(ngModel)]="cliente.nome" >
<div class="form-control-feedback" [hidden]="nome.valid || nome.pristine">O campo deve ser informado</div>
</div>
......
.....
|
Você verá o formulário com o mesmo comportamento funcionando como anteriormente.
Agora vamos repetir o procedimento criando a classe para aplicar os estilos no form control e depois vamos aplicar as classes aos demais campos do formulário.
O código do arquivo cliente-detalhe.component.ts deve ficar assim:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params} from '@angular/router';
import { Location } from '@angular/common';
import { Cliente } from './cliente.model';
import { ClienteService } from './cliente.service';
@Component({
moduleId: module.id,
selector : 'cliente-detalhe',
templateUrl : 'cliente-detalhe.component.html'
})
export class ClienteDetalheComponent implements OnInit {
cliente : Cliente;
constructor(
private clienteService : ClienteService,
private route : ActivatedRoute,
private location : Location
) {}
ngOnInit(): void {
this.cliente = new Cliente(0,'','','',);
this.route.params.forEach((params: Params)=>{
let id: number = +params['id'];
if(id){
this.clienteService.getCliente(id)
.then((cliente: Cliente)=> {
console.log(cliente);
this.cliente = cliente;
});
}
});
}
getFormGroupClass(isValid : boolean, isPristine: boolean) : {} {
return {
'form-group' : true,
'has-danger': !isValid && !isPristine,
'has-success': isValid && !isPristine
};
}
getFormControlClass(isValid : boolean, isPristine: boolean) : {} {
return {
'form-control' : true,
'has-danger': !isValid && !isPristine,
'has-success': isValid && !isPristine
};
}
}
|
E a aplicação das classes no template html deve ficar assim: (O código alterado esta em azul)
<div class="container">
<h2>Salvar Cliente</h2>
<form #clienteForm="ngForm" novalidate>
<div [ngClass]="getFormGroupClass(nome.valid,nome.pristine)">
<label for="nome" class="form-control-label">Nome</label>
<input type="text" placeholder="Informe o nome"
[ngClass]="getFormControlClass(nome.valid, nome.pristine)"
required
#nome="ngModel"
name="nome"
[(ngModel)]="cliente.nome" >
<div class="form-control-feedback" [hidden]="nome.valid || nome.pristine">O campo nome deve ser informado</div>
</div>
<div [ngClass]="getFormGroupClass(email.valid, email.pristine)">
<label for="email">Email</label>
<input type="email" class="form-control" placeholder="Informe o email"
[ngClass]="getFormControlClass(email.valid, email.pristine)"
required
#email="ngModel"
name="email"
[(ngModel)]="cliente.email" >
<div class="form-control-feedback" [hidden]="email.valid || email.pristine">O campo email deve ser informado</div>
</div>
<div [ngClass]="getFormGroupClass(telefone.valid,telefone.pristine)">
<label for="telefone">Telefone</label>
<input type="text" class="form-control" placeholder="Informe o telefone"
[ngClass]="getFormControlClass(telefone.valid, telefone.pristine)"
required
#telefone="ngModel"
name="telefone"
[(ngModel)]="cliente.telefone">
<div class="form-control-feedback" [hidden]="telefone.valid || telefone.pristine">O campo telefone deve ser informado</div>
</div>
<button type="submit" class="btn btn-success" [disabled]="!clienteForm.form.valid">Salvar</button>
<a class="btn btn-secondary" routerLink="/">Voltar </a>
</form>
</div>
|
E assim, concluimos a etapa da validação do formulário para nossa aplicação. Embora seja uma validação simples ela esta funcional e te da uma idéia dos recursos que o Angular oferece.
No próximo artigo vamos abordar o envio ou submit do formulário e a diretiva ngsubmit.
Pegue o código do projeto aqui : cadastro_Clientes_Angular.zip (sem a pasta node_modules)
Mas a hora vem, e agora é, em que os
verdadeiros adoradores adorarão o Pai em espírito e em verdade; porque o Pai
procura a tais que assim o adorem.
Deus é Espírito, e importa que os que o adoram o adorem em espírito e em
verdade.
João 4:23,24
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
NET - Criando um livro de contatos usando o AngularJS - Macoratti
NET - AngularJS : Apresentação (início do curso) - Macoratti
ASP .NET MVC - Crud com Entity Framework e AngularJS - Macoratti
AngularJS - Conceitos Básicos - YouTube (série de 13 vídeo aulas sobre o Angular)
NET - O que é TypeScript e quais os seus benefícios - Macoratti
TypeScript - Configurando o VS Community 2015 para ... - Macoratti
Visual Studio - Bem-Vindo Node.js : desenvolvendo para Node.js na plataforma .NET