envio_de_dados_para_o_servidor - VWJavascript/Alurapic GitHub Wiki
Envio de dados para o servidor
Agora que temos acesso aos dados da foto com base nos valores do formulário, precisamos enviá-la para nosso servidor. Até agora usamos apenas o verbo GET para obter uma lista de fotos para o recurso v1/fotos. Dessa vez, usaremos o mesmo identificador do recurso, mas empregaremos o verbo POST, muito usado quando queremos incluir dados. Você ainda lembra como temos acesso ao serviço HTTP? Você aprendeu que podemos receber por injeção baseada em tipo a dependência do tipo Http no constructor da nossa classe:
// alurapic/client/app/cadastro/cadastro.component.ts
import { Component, Input } from '@angular/core';
import { FotoComponent } from '../foto/foto.component';
import { Http } from '@angular/http';
@Component({
moduleId: module.id,
selector: 'cadastro',
templateUrl: './cadastro.component.html'
})
export class CadastroComponent {
foto: FotoComponent = new FotoComponent();
constructor(http: Http) {
// o que eu faço agora?
}
cadastrar(event) {
event.preventDefault();
console.log(this.foto);
}
}
Como faremos para ter acesso ao Http em nosso método cadastrar? Uma solução é criar uma nova propriedade em nossa classe, que receberá o serviço Http injetado no construtor. Propriedades de classe podem ser acessadas em qualquer método da classe:
// alurapic/client/app/cadastro/cadastro.component.ts
import { Component, Input } from '@angular/core';
import { FotoComponent } from '../foto/foto.component';
import { Http } from '@angular/http';
@Component({
moduleId: module.id,
selector: 'cadastro',
templateUrl: './cadastro.component.html'
})
export class CadastroComponent {
foto: FotoComponent = new FotoComponent();
http: Http;
constructor(http: Http) {
this.http = http;
}
cadastrar(event) {
event.preventDefault();
console.log(this.foto);
// agora posso acessar http através de this.http
}
}
Mais um problema resolvido. Agora, no método cadastrar, vamos solicitar ao nosso serviço Http que realize uma requisição do tipo POST:
// alurapic/client/app/cadastro/cadastro.component.ts
// código anterior omitido
cadastrar(event) {
event.preventDefault();
console.log(this.foto);
this.http.post('v1/fotos', JSON.stringify(this.foto));
}
}
O primeiro parâmetro da função http.post é o endereço do recurso do nosso servidor, no caso o mesmo endereço que usamos para obter uma lista de fotos. Qual a diferença então? A diferença é que nosso servidor está preparado para executar uma ação específica para os verbos POST e GET, mesmo que o endereço seja o mesmo.
O segundo parâmetro é nossa foto. Porém, não podemos simplesmente pegar esse objeto e enviá-lo como parâmetro. O padrão JSON é um formato somente texto e é exatamente uma string (JSON) o segundo parâmetro. Precisamos antes transformar o objeto em JSON (texto) através de JSON.stringify. Mas não é apenas isso. Além do dado que estamos enviando, precisamos adicionar uma informação especial no header da requisição dizendo o tipo de conteúdo que estamos enviado para o servidor. Essa informação é importante, porque o servidor pode estar preparado para lidar com diferentes tipos.
Há uma classe do Angular que representa os Headers do HTTP. Vamos importá-la do módulo angular2/http, criar um um objeto a partir dela para que possamos adicionar nossas configurações e passá-lA como parâmetro para a função http.post:
// alurapic/client/app/cadastro/cadastro.component.ts
import {Component} from '@angular/core';
import {Http, Headers} from '@angular/http'; // importou a classe Header também
import { FotoComponent } from '../foto/foto.component';
@Component({
moduleId: module.id,
selector: 'cadastro',
templateUrl: './cadastro.component.html'
})
export class Cadastro {
foto: FotoComponent = new FotoComponent();
http: Http;
constructor(http: Http) {
this.http = http;
}
cadastrar() {
console.log(this.foto);
// cria uma instância de Headers
let headers = new Headers();
// Adiciona o tipo de conteúdo application/json
headers.append('Content-Type', 'application/json');
this.http.post('v1/fotos', JSON.stringify(this.foto), { headers: headers });
}
}
Muita atenção, porque não passamos nosso objeto headers diretamente. Passamos um objeto com a propriedade headers que o contém como valor.
E agora? Lembra da função .subscribe?
// alurapic/client/app/cadastro/cadastro.component.ts
import {Component} from '@angular/core';
import {Http, Headers} from '@angular/http';
import { FotoComponent } from '../foto/foto.component';
@Component({
moduleId: module.id,
selector: 'cadastro',
templateUrl: './cadastro.component.html'
})
export class Cadastro {
foto: FotoComponent = new FotoComponent();
http: Http;
constructor(http: Http) {
this.http = http;
}
cadastrar() {
console.log(this.foto);
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('v1/fotos', JSON.stringify(this.foto), { headers: headers })
.subscribe(() => {
this.foto = new FotoComponent();
console.log('Foto salva com sucesso');
}, erro => console.log(erro));
}
}
As arrow functions estão de volta! Veja que na primeira função, executada quando a operação é efetuada com sucesso, recebemos a foto de volta do servidor, com seu ID preenchido. Podemos até imprimir seu ID no console. Em seguida, apagamos os dados da foto para que o formulário fique em branco, o que faz todo sentido. Por fim, exibimos uma mensagem de sucesso (Foto gravada com sucesso) e logamos qualquer erro que possa ocorrer. Mais tarde aprenderemos a dar uma mensagem mais amigável para os usuário.