Olá, no último post sobre Angular 2 vimos como configurar rotas. Hoje veremos como usar services com requisições HTTP, fazendo um exemplo simples que consome uma API Node.js com banco de dados SQLite.
Downloads
A única coisa que vamos precisar baixar é o bootstrap.
Estrutura da aplicação
Nossa aplicação terá uma estrutura simples:
API
package.json
Como eu disse antes será uma API simples, que estará no arquivo server.js, mas antes disso vamos criar nosso arquivo package.json onde teremos as dependências.
{ "name": "angular2-services-http", "version": "1.0.0", "description": "Exemplo de como usar services em Angular2", "main": "server.js", "scripts": { "test": "node server" }, "dependencies":{ "express":"latest", "sqlite-sync":"latest", "body-parser":"latest" } }
Depois de ter criado esse arquivo na pasta raiz da sua aplicação, execute o seguinte comando:
$ npm install
Para instalar as dependências. Note que todos os pacotes instalados estão na versão mais recente (latest), você pode mudar para a versão que preferir de cada um.
server.js
Nesse arquivo estará a nossa API, que deve ter os métodos HTTP GET, POST, PUT e DELETE, para listar, cadastrar, editar e excluir pessoas.
Nele também estará nossa conexão com o banco de dados, na qual usamos o módulo sqlite-sync que funciona de forma síncrona ou assíncrona. Veja mais detalhes sobre ele aqui. O arquivo de banco de dados será criado automaticamente pelo módulo dentro da pasta model, caso não exista.
Vamos ao arquivo:
var express = require('express'), app = express(), router = express.Router(), bodyParser = require('body-parser'), path = require('path'), sqlite = require('sqlite-sync'); sqlite.connect('./model/database.db'); sqlite.run("CREATE TABLE pessoas (id INTEGER PRIMARY KEY AUTOINCREMENT, nome CHAR(100), email CHAR(100));"); var exec = require('child_process').exec; app.use(bodyParser.json()); app.use('/app', express.static(path.join(__dirname,'/app'))); app.use('/bootstrap', express.static(path.join(__dirname,'/bootstrap'))); app.use('/angular2', express.static(path.join(__dirname,'/angular2'))); app.get('/', function (req, res) { res.sendFile(path.join(__dirname, 'index.html')); }); app.get('/api/pessoas', function(req,res){ res.send(sqlite.run("SELECT * FROM pessoas")); }); app.post('/api/pessoas', function(req, res){ sqlite.insert('pessoas', req.body, function(id){ res.send({'id':id}); }); }); app.put("/api/pessoas/:id", function(req, res){ var id = req.params.id; var body = req.body; sqlite.update('pessoas', body, {id:id}, function(result){ res.send({result : result}); }); }); app.delete('/api/pessoas/:id', function(req, res){ var id = req.params.id; sqlite.delete('pessoas',{id: id}, function(result){ res.send({result : result}); }); }); app.listen(3000, function(){ exec('start http://localhost:3000'); });
Note que na linha 10 criamos a tabela no banco de dados. Você pode fazer isso por meio de outro aplicativo SGBD se quiser, como SQLite Studio por exemplo.
Aplicação
Agora vamos à aplicação que vai consumir a API, conforme estrutura de pastas e arquivos mostrada mais acima. Nossa aplicação terá apenas uma única página e não precisa de rotas.
index.html
Vamos começar pelo arquivo principal da aplicação, que deve conter as configurações para uso do TypeScript com SystemJS, como visto no post TypeScript – executando no browser com SystemJS.
<!DOCTYPE html> <html> <head> <script>document.write('<base href="' + document.location + '" />');</script> <title>Angular2 - Service HTTP</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.css"> <!-- jQuery --> <script src="http://code.jquery.com/jquery-1.12.0.min.js"></script> <!-- Bootstrap --> <script src="bootstrap/js/bootstrap.js"></script> <!-- IE required polyfills, in this exact order --> <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system-polyfills.js"></script> <script src="https://npmcdn.com/angular2@2.0.0-beta.17/es6/dev/src/testing/shims_for_IE.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system.js"></script> <script src="https://npmcdn.com/typescript@1.8.10/lib/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.17/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.17/angular2.dev.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.17/http.dev.js"></script> <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'app': {defaultExtension: 'ts'}} }); System.import('app/main') .then(null, console.error.bind(console)); </script> </head> <body> <my-app>Loading...</my-app> </body> </html>
Na linha 24 é importado o arquivo http.dev.js, que possibilita o uso das diretivas HTTP.
app/main.ts
Este arquivo inicia nossa aplicação Angular 2.
import { bootstrap } from 'angular2/platform/browser'; import 'rxjs/Rx'; import { HTTP_PROVIDERS } from 'angular2/http'; import { AppComponent } from './app.component'; bootstrap(AppComponent, [HTTP_PROVIDERS]);
Na linha 3 importamos os HTTP_PROVIDERS, o que nos possibilita o uso de requisições HTTP.
app/app.component.ts
Nosso componente principal, tem a função de controlar o html, criando nossa aplicação na tag informada como seletor.
import { Component, Input} from 'angular2/core'; import { HTTP_PROVIDERS } from 'angular2/http'; // Services import { PessoaService } from './pessoa.service'; @Component({ selector: 'my-app', templateUrl: 'app/view.html', providers: [ PessoaService, HTTP_PROVIDERS ] }) /** * Classe AppComponent */ export class AppComponent { /** * Atributos */ private id: number; private nome, email: string; private pessoas: Array[]; private pessoa: AppComponent = {}; /** * Método construtor * @param _service: PessoaService */ constructor(private _service: PessoaService){ this.getPessoas(); } /** * Listando pessoas */ getPessoas(){ this._service.getPessoas() .then(pessoas => {this.pessoas = pessoas}); } /** * Salvar pessoa */ salvar(){ if(this.pessoa.id){ this._service.editar(this.pessoa).then(res => { this.getPessoas(); $('#myModal').modal('hide'); }); }else{ this._service.novo(this.pessoa).then(res => { this.getPessoas(); $('#myModal').modal('hide'); }); } } /** * Editar pessoa * @param item: Array */ editar(item){ this.pessoa = item; $('#myModal').modal('show'); } /** * Excluir pessoa * @param item: Array */ excluir(item){ if(confirm("Você tem certeza que deseja excluir?")){ this._service.excluir(item.id).then(res => { this.getPessoas(); }); } } /** * Cancelar Cadastro */ cancelar(){ this.pessoa = {}; $('#myModal').modal('hide'); } }
Note que na linha 5 importamos o service do arquivo pessoa.service.ts que é onde teremos as requisições HTTP.
app/pessoa.service.ts
Nosso service, que usando da classe Http realiza GET, POST, PUT e DELETE.
import {Injectable} from 'angular2/core'; import {Http, Headers,RequestOptions } from 'angular2/http'; @Injectable() /** * Service Pessoa */ export class PessoaService { private apiUrl = 'api/pessoas'; // URL para web api /** * Método construtor * @param http: Http */ constructor(private http: Http) { } /** * Listando pessoas */ getPessoas(){ return this.http.get(this.apiUrl) .toPromise() .then(response => response.json()) .catch(this.handleError); } /** * Nova pessoa * @param pessoa: Array * @return http POST */ novo(pessoa: Array){ let body = JSON.stringify(pessoa); let headers = new Headers({'Content-Type': 'application/json'}); let options = new RequestOptions({ headers: headers }); return this.http.post(this.apiUrl, body, options) .toPromise() .then(res => res.json()) .catch(this.handleError); } /** * Editar pessoa * @param pessoa: Array * @return http PUT */ editar(pessoa: Array){ let id = pessoa.id; delete pessoa.id; let body = JSON.stringify(pessoa); let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); let url = this.apiUrl + '/' + id; return this.http.put(url, body, options) .toPromise() .then(res => res.json()) .catch(this.handleError); } /** * Excluir pessoa * @param id: number * @return http DELETE */ excluir(id: number){ let url = this.apiUrl + '/' + id; return this.http.delete(url) .toPromise() .then(res => res.json().data) .catch(this.handleError); } }
app/view.html
Arquivo HTML que será controlado pelo nosso componente Angular2.
<div class="container"> <h2>Cadastro de Pessoas</h2> <hr> <div class="row"> <div class="col-md-6"> <button class="btn btn-primary" data-toggle="modal" data-target="#myModal"><i class="fa fa-plus"></i> Novo</button> </div> </div> <hr> <div class="row"> <div class="col-md-12"> <table class="table"> <thead> <tr> <th>#</th> <th>Name</th> <th>E-mail</th> <th></th> </tr> </thead> <tbody> <tr *ngFor="let pessoa of pessoas"> <td>{{pessoa.id}}</td> <td>{{pessoa.nome}}</td> <td>{{pessoa.email}}</td> <td> <button (click)="editar(pessoa)" class="btn btn-xs btn-info">Editar</button> <button (click)="excluir(pessoa)" class="btn btn-xs btn-danger">Excluir</button> </td> </tr> </tbody> </table> </div> </div> </div> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">Cadastro</h4> </div> <div class="modal-body"> <div class="form-group"> <label>Nome:</label> <input type="text" class="form-control" [(ngModel)]="pessoa.nome"> </div> <div class="form-group"> <label>E-mail:</label> <input type="email" class="form-control" [(ngModel)]="pessoa.email" > </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" (click)="cancelar()" >Cancelar</button> <button type="button" class="btn btn-primary" (click)="salvar()">Salvar</button> </div> </div> </div> </div>
Executando
Para executar sua aplicação rode o seguinte comando no bash, prompt ou terminal:
$ npm test
Ou
$ node server
Concluindo
Este é o terceiro post da série sobre Angular2. Você pode ter acesso ao código fonte no Git Hub. Até a próxima.
Boa tarde
Achei o artigo bem resumido e pratico.
Sou novo no angular e tenho tentado implementar um exemplo que fiz com spring mvc, é o seguinte
Não consigo implememntar uma venda com itens por exemplo
cliente: joao
produto: cerveja x
quantidade: 2
valor: 20
Quero salvar o cliente na tabela vendas e o produto na tabela itens.
Obrigado