Angular 2 - Vinculando uma lista em um Select - Seleção em cascata - II
Neste artigo vou mostrar como vincular uma lista de dados em um Select Dropdown em uma aplicação Angular 2 usando o Visual Studio Code. |
Continuando a primeira parte do artigo veremos agora como implementar seleção em cascata onde teremos agora dois componentes Select onde em um serão exibidos os países e conforme o país selecionado no outro serão exibidas as cidades do respectivo país.
Nosso ponto de partida será o projeto criado no artigo anterior.
Definindo um Serviço Angular e a classe para cidades
Para
poder exibir uma segunda lista com as cidades de um pais selecionado vamos criar
uma classe onde vamos definir a lista de cidades para cada país.
E vamos fazer isso usando um serviço e não definir o código no componente como
haviamos feito no artigo anterior.
Então vamos criar um serviço Angular e depois usar este serviço no nosso
componente. Esta abordagem é mais recomendada e aderente às boas práticas, pois
se no futuro mudarmos a forma de como obter os dados não teremos que alterar o
componente.
Um serviço Angular pode obter dados de um arquivo JSON, de uma API da Web, ou de
Serviço da Web ou de qualquer outro armazenamento local.
Quem vai consumir o serviço não está se importando como o serviço está obtendo os dados. Portanto, para o nosso serviço, vamos criar uma classe chamada "DataserviceService" com dois métodos que retornam um array de países e estados.
Criando a classe Cidade
No VS Code crie o arquivo cidade.ts na pasta app com o código abaixo:
Definimos acima a classe Cidade com 3 propriedades : id , paisid e nome.
Criando o serviço Angular: DataService
Agora vamos criar o serviço angular e para isso vamos usar o Angular CLI.
Na janela do prompt de comandos posicione-se na pasta do projeto e digite o comando : ng g service dataservice
Foram criados dois arquivos seguindo o style guide do Angular:
Observe que temos uma alerta informando que o serviço foi gerado mas precisa ser fornecido para ser usado.
Outro detalhe importante a ressaltar é que quanto criamos o serviço usando o Angular CLI ele já incluir o import do serviço na classe app.component.ts.
Abrindo o projeto no VS Code veremos os arquivos criados e o código do arquivo dataservice.service.ts conforme abaixo:
As declarações no Angular são definidas assim : @Nome , e isso é um decorator.
Os decorators ou decoradores são uma extensão proposta para o JavaScript e permitem modificar e/ou marcar métodos, classes, propriedades e parâmetros.
Existem muitos decoradores, e, no código acima estamos usando dois decoradores muito importantes para a injeção de dependência (DI) : @Inject e @ Injectable
Nossa classe esta usando o decorator @Injectable() e por isso tivemos que importar a função Injectable do Angular para aplicarmos o decorador a essa função ( @Injectable() )
Vamos alterar o código do arquivo conforme abaixo:
import { Injectable } from '@angular/core';
import { Pais } from './pais';
import { Cidade } from './cidade'
@Injectable()
export class DataserviceService {
getPaises() {
return [
new Pais(1, 'Brasil' ),
new Pais(2, 'USA' ),
new Pais(3, 'Itália' )
];
}
getCidades() {
return [
new Cidade(1, 1, 'São Paulo' ),
new Cidade(2, 1, 'Brasília' ),
new Cidade(3, 1, 'Rio de Janeiro'),
new Cidade(4, 1, 'Santos'),
new Cidade(5, 2, 'New Yord' ),
new Cidade(6, 2, 'Chicago'),
new Cidade(7, 2, 'Los Angeles' ),
new Cidade(8, 3, 'Roma' ),
new Cidade(9, 3, 'Florença' ),
new Cidade(10, 3, 'Veneza')
];
}
constructor() { }
}
|
Definimos dois métodos :
Agora precisamos alterar o código do nosso componente definido no arquivo app.component.ts.
Abra este arquivo e altere o seu código conforme abaixo:
import { DataserviceService } from './dataservice.service';
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { Pais } from './pais';
import { Cidade } from './cidade';
@Component({
selector: 'minha-lista-paises',
templateUrl : './app.component.html',
providers : [DataserviceService]
})
export class AppComponent {
paises : Pais[];
cidades : Cidade[];
constructor(private _dataService: DataserviceService) {
this.paises = this._dataService.getPaises();
}
}
|
Destaques do código acima:
1 - O
import do serviço feito - DataserviceService - pelo o Angular CLI
2 - O import das classes Pais e Cidade
A seguir vamos injetar o nosso serviço no componente e para isso precisamos adicionar dois recursos ao código:
1 - Adicionar um construtor que defina uma propriedade privada;
constructor(private _dataService:
DataserviceService) {
this.paises = this._dataService.getPaises();
}
2 - Adicionar o metada providers - O array providers informa ao Angular para
criar uma nova instância do DataserviceService quando ele criar um
AppComponent. O AppComponent, bem como seus componentes filho, podem usar
esse serviço para obter dados das cidades e paises.-
providers : [DataserviceService]
Agora podemos ajustar o arquivo app.component.html que vai exibir as
informações ao usuário.
Abra o arquivo app.component.html na pasta app e altere o seu código conforme abaixo:
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<h2>Selecione o Pais: </h2>
<select class="form-control">
<option *ngFor="let pais of paises" value= {{pais.id}}>
{{pais.nome}}
</option>
</select>
|
Este eu apenas inclui as referência CDN do bootstrap para dar uma aparência melhor à página.
O código praticamente não houve alteração. Executando novamente o projeto e abrindo o navegador em : http://localhost:4200 obtemos o seguinte resultado:
Tudo bem, mas isso é o mesmo resultado do artigo anterior. Agora vamos implementar o segundo select e o evento que irá permitir saber qual o pais foi selecionado para assim podermos obter as respectivas cidades deste país.
Implementando a seleção em cascata
Para implementar a seleção em cascata vamos primeiro alterar o código do arquivo app.component.html conforme abaixo:
<!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <!-- jQuery library --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <!-- Latest compiled JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <h2>País: </h2> <select class="form-control" [(ngModel)]="paisSelecionado.id" (change)="onSelect($event.target.value)" id="sel1"> <br> <div> |
Neste código incluímos a diretiva [(ngModel)]="paisSelecionado.id" para obter o id do pais selecionado e vamos fazer isso toda vez que um pais for selecionado definindo o evento (change) com o nome onSelect e usando o objeto $event para obter o valor selecionado pelo usuário.
Quando o evento change é disparado, $event.target representa quem disparou o evento. Sendo um elemento do DOM, podemos acessar seu valor com $event.target.value. É este valor que é atualizado na propriedade paisSelecionado.id.
Nota: Todos os objetos de evento DOM padrão possuem uma propriedade de target, uma referência ao elemento que gerou o evento. Neste caso, target refere-se ao elemento <select> e event.target.value retorna o conteúdo atual desse elemento que é o pais selecionado.
A seguir definimos outro elemento o <select> para exibir as cidades do pais selecionado. Para isso estamos usando a diretiva *ngIf.
A diretiva ‘*ngIf’ recebe como parâmetro um valor booleano, que indicará se o elemento deverá ou não ser exibido na tela. O parâmetro pode ser uma expressão, a chamada para um método do componente, ou um simples atributo de classe, más o importante é que o valor passado retorne um valor booleano.
A seguir usamos novamente a diretiva *ngFor para percorrer o array de cidades do pais selecionado exibindo-as na página.
Ajuste o código do arquivo app.component.ts conforme abaixo:
import { DataserviceService } from './dataservice.service';
import { Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { Pais } from './pais';
import { Cidade } from './cidade';
@Component({
selector: 'minha-lista-paises',
templateUrl : './app.component.html',
providers : [DataserviceService]
})
export class AppComponent {
paisSelecionado : Pais = new Pais(0,'Brasil') ;
paises : Pais[];
cidades : Cidade[];
constructor(private _dataService: DataserviceService) {
this.paises = this._dataService.getPaises();
}
onSelect(id) {
this.cidades = this._dataService.getCidades().filter((item)=> item.paisid == id);
}
}
|
Incluimos a definição da variável paisSelecionado do tipo Pais atribuindo um valor padrão.
Definimos o código do evento onSelect() que será acionado sempre que o usuário selecionar um país. Neste caso filtramos as cidades pelo id do pais selecionado e atribuímos ao array cidades.
Ajustando o arquivo app.module.ts
O arquivo
app.module.ts define o módulo raiz do aplicativo. Nele, você identifica
os módulos externos que você usará no aplicativo e declarará os componentes que
pertencem a este módulo.
Como os formulários orientados por modelo estão em seu próprio módulo, você
precisa adicionar o FormsModule à matriz de importações para o módulo de
aplicativo antes de poder usar formulários.
Para concluir temos que incluir uma referência a FormsModule no arquivo app.module.ts
import { DataserviceService } from './dataservice.service';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
|
Agora tudo esta pronto. Para testar vamos abrir uma nova janela de prompt de comando na pasta do projeto e digitar o comando : ng serve
Nota: podemos também digitar : npm start
Abrindo um navegador e digitando a url : http://localhost:4200 iremos obter o seguinte :
E assim implementamos uma seleção em cascata simples no Angular 2.
Pegue o projeto, sem as referências, aqui : selecaoCascata.zip
Todas as coisas são puras para os puros,
mas nada é puro para os contaminados e infiéis; antes o seu entendimento e
consciência estão contaminados.
Confessam que conhecem a Deus, mas negam-no com as obras, sendo abomináveis, e
desobedientes, e reprovados para toda a boa obra.
Tito 1:15,16
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