isolando_resposabilidade - VWJavascript/Alurapic GitHub Wiki
Nossa aplicação consegue incluir e alterar, porém nossa solução ainda não está cem porcento. Veja que tanto para um inclusão quanto para alteração estamos navegando para ListagemComponent. No entanto, queremos que o usuário continue em CadastroComponent caso ele tenha feito uma inclusão permitindo assim que ele cadastre mais fotos.
Outro ponto é que a mensagem de inclusão ou alteração são definidas em CadastroComponent. Se usarmos FotoService em outro local da nossa aplicação teremos que repetir as mesmas mensagens.
Uma solução é fazer com que o método cadastra de FotoService passse a retornar um objeto que contenha duas propriedades para guardar a mensagem e e um boleano para indicar se foi inclusão ou não. Hoje nosso método retorna um Observable, com a nossa alteração ele passará a retorna um Observable:
// alurapic/client/app/foto/foto.service.ts
// código anterior omitido
cadastra(foto: FotoComponent): Observable<Object> {
if(foto._id) {
return this.http.put(this.url + '/' + foto._id, JSON.stringify(foto),
{ headers: this.headers })
.map(() => ({mensagem: 'Foto alterada com sucesso', inclusao: false}));
} else {
return this.http.post(this.url, JSON.stringify(foto),
{ headers: this.headers })
.map(() => ({mensagem: 'Foto incluída com sucesso', inclusao: true}));
}
}
Tanto na alteração quando na inclusão a função map agora retorna um objeto com as propriedades mensagem e inclusao. O primeiro contém a mensagem da operação e o segundo true se for uma inclusão e false se for uma alteração. Você deve ter achado um tanto estranho envolver nosso objeto entre parênteses, mas essa é uma exigência quando retornamos em uma única linha um objeto {}. Se não envolvermos com parênteses nossa arrow function confundirá as chaves do objeto com a chave de um bloco resultando em um erro de compilação.
Agora, vamos alterar nosso CadastroComponent para pegar carona no novo tipo de retorno:
// alurapic/client/app/cadastro/cadastro.component.ts
// código anterior omitido
cadastrar(event) {
event.preventDefault();
console.log(this.foto);
this.service
.cadastra(this.foto)
.subscribe(res => {
this.mensagem = res.mensagem;
this.foto = new FotoComponent();
if(!res.inclusao) this.router.navigate(['']);
}, erro => {
console.log(erro);
this.mensagem = 'Não foi possível savar a foto';
});
}
Um pouco mais sobre tipagem e o tipo any Temos um erro de compilação no método cadastra de CadastroComponent. O TypeScript é bem enfático e nos diz que res.mensagem e res.inclusao não existem para o tipo Object. Realmente, o tipo Object não possui qualquer um desses métodos. Como resolver?
Em TypeScript podemos usar o tipo any para indicar tipo retornado é qualquer tipo. Na verdade ele foi adicionados aos tipos deste superset do ES6 para possibilitar sua introdução em sistema legados, quando não há uma maneira clara de especificar o tipo. Vamos alterar o tipo de retorno de cadastro em FotoService:
// alurapic/client/app/foto/foto.service.ts
// código anterior omitido
cadastra(foto: FotoComponent): Observable<any> {
// código omitido
}
Com essa alteração nosso código compila perfeitamente, no entanto não temos recurso de autocomplete muito menos checagem de tipos.