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.

image