7
respostas

Cadastro das fotos

https://github.com/KynnMaia/curso-angular

EXCEPTION: Error in http://localhost:3000/app/listagem/listagem.component.html:23:16 caused by: Cannot read property 'toLowerCase' of undefined

erro ao implementar a função de cadastro, ainda não consegui identificar o erro, creio que seja no servidor.

7 respostas

Boa tarde! Em ListagemComponent.ts, você definiu o valor padrão para ao atributo que receberá o filtro do usuário? Se não fizer isso, o valor será undefined assim que sua página renderizar as fotos vindas do servidor e você terá esse erro.

Ela precisa ser inicializada com uma string em branco. Dá uma conferida.

tem como mostrar onde ?

Cole o código de ListagemCompinent.ts e CadastroComponent.ts.

Você diz que é erro no Cadastro mas a mensagem de erro é em ListagemComponent.

Poste também o template dos dois componentes.

listagem.component.ts

import { Component } from "@angular/core";
import { Http } from "@angular/http";

@Component({
    moduleId: module.id,
    selector: 'listagem',
    templateUrl: './listagem.component.html'
})
export class ListagemComponent{

    fotos: Object[] = [];
    //esse parametro faz um inject automatica;
    constructor(http: Http){

        http
        .get('v1/fotos')
        .map( res => res.json())
        //res => == function(res)
        .subscribe(fotos => {
            this.fotos = fotos;
            //console.log(this.fotos);
        }, erro => console.log(erro));
    }    
}

cadastro.component.ts

import { Component } from "@angular/core";
import { FotoComponent } from "../foto/foto.component";
import { Http, Headers } 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();

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        //transformando o objeto javascript em texto 
        this.http.post('v1/fotos', JSON.stringify(this.foto), { headers: headers }).subscribe(() => {
            console.log("foto salva com sucesso");
        });
    }
}

Faltou compartilhar o template dos dois componentes. Todavia, se por algum motivo, na hora de criar o cadastro, você errou no data binding da propriedade título, os dados gravados na API não terão o título e você receberá esse erro.

Poste o template dos dois componentes e o código do seu pipe, porque é ele que esta disparando esse erro quando alguma foto é trazida do servidor e não possui título.

listagem,component.html

<div class="jumbotron">
    <h1 class="text-center">Alurapic</h1>
</div>

<div class="container">

    <div class="row">
        <div class="col-md-12">
            <form>
                 <div class="input-group">
                    <span class="input-group-btn">
                        <a [routerLink] = "['/cadastro']" class="btn btn-primary">
                            Nova foto
                        </a>
                    </span>
                    <!-- (keyup)="0" faz pesquisa ao digitar -->
                    <input #textoProcurado (keyup)="0" class="form-control" placeholder="filtrar pelo titulo da foto">
                </div> 
            </form>
        </div> <!-- fim col-md-12 -->
    </div> <!-- fim row -->
    <br>
    <div class="row">
        <painel *ngFor="let foto of fotos | filtroPorTitulo: textoProcurado.value" titulo="{{foto.titulo | uppercase }}" class="col-md-2">
            <foto titulo="{{foto.titulo}}" url="{{foto.url}}">
            </foto>
        </painel>
    </div><!-- fim row -->
</div>

cadastro.component.html

<div class="container">
    <form (submit)="cadastrar($event)" class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label>Título</label>
                <input name="titulo" [(ngModel)]="foto.titulo" class="form-control"  autocomplete="off">    
            </div>
            <div class="form-group">
                <label>URL</label>
                <input name="url" [(ngModel)]="foto.url" class="form-control"  autocomplete="off">
            </div>
            <div class="form-group">
                <label>Descrição</label>
                <textarea name="descricao" [(ngModel)]="foto.descricao" class="form-control"  autocomplete="off">
                </textarea>
            </div>

            <button type="submit" class="btn btn-primary">
                Salvar
            </button>
                <a [routerLink]="['']" class="btn btn-primary">Voltar</a>
            <hr>
        </div>
    </form>
</div>

foto.pipes.ts

import { Pipe, PipeTransform } from "@angular/core";
import { FotoComponent } from "./foto.component";


@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform{


    transform(fotos: FotoComponent[], digitado: string){
        digitado = digitado.toLowerCase();        
        return fotos.filter( foto => foto.titulo.toLowerCase().includes(digitado));
    }
}

Se em algum momento, seu CadastroComponent.html não realizou o binding para a propriedade titulo ela foi gravada como undefined no banco e quando você for exibir ListagemComponent.html terá esse erro.

Uma maneira de se blindar sem ter que apagar o banco é fazer o seguinte:

import { Pipe, PipeTransform } from "@angular/core";
import { FotoComponent } from "./foto.component";


@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform{


    transform(fotos: FotoComponent[], digitado: string){
        digitado = digitado.toLowerCase();        

        return fotos.filter( foto => {
            if(foto.titulo) {
                return foto.titulo.toLowerCase().includes(digitado)
            } else {
                return false;
            }
        });
    }
}