Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

Mostrar imagem da url com problemas. Aparecendo undefined antes de informar a url

Olá, na última aula do curso parte 1, é feito um link para que quando eu informe a url da imagem, a imagem já apareça ao lado do formulário.

O que ocorre é que enquanto eu não tiver informado a url, ele mostra "undefined" onde deveria aparecer a foto.

Notei que no vídeo não aconteceu isso com o instrutor. É alguma configuração do navegador?

Conferi aqui, e acredito que meu código esteja igual ao da aula.

<div class="container">
    <h1 class="text-center">
        {{foto.titulo}}
    </h1>
    <form [formGroup]="meuForm" class="row" (submit)="cadastrar($event)">
        <div class="col-md-6">
            <div class="form-group">
                <label for="">
                    Título
                </label>

                <input type="text" formControlName="titulo" name="titulo" [(ngModel)]="foto.titulo" class="form-control" autocomplete="off">
                <div *ngIf="meuForm.controls.titulo.invalid">
                    <!-- Pega a validação somente do Validators.titulo -->
                    <span *ngIf="meuForm.controls.titulo.errors.required" class="form-control alert-danger">Título obrigatório</span>
                    <span *ngIf="meuForm.controls.titulo.errors.minlength" class="form-control alert-danger">Mínimo de 4 caracteres</span>
                </div>
            </div>
            <div class="form-group">
                <label for="">
                    URL
                </label>
                <input type="text" formControlName="url" name="url" [(ngModel)]="foto.url" class="form-control" autocomplete="off">
                <span *ngIf="meuForm.controls.url.invalid" class="form-control alert-danger">URL obrigatória</span>
            </div>
            <div class="form-group">
                <label for="">
                    Descrição
                </label>
                <textarea class="form-control" formControlName="descricao" name="descricao" [(ngModel)]="foto.descricao" autocomplete="off"></textarea>
            </div>

            <button type="submit" class="btn btn-primary" [disabled]="meuForm.invalid">Salvar</button>
            <a [routerLink]="['']" class="btn btn-primary">Voltar</a>
            <hr>
        </div>
        <div class="col-md-6">
            <foto [url]="foto.url" [titulo]="foto.titulo"></foto>
        </div>
    </form>
</div>
10 respostas

Poste o código dos seus componentes. Uma img com url inválida exibe seu alt. Se está saindo undefined é problema no modelo. Teria que exibir o nome da foto.

foto.component

import { Component, Input } from '@angular/core'; // Input serve para que o meu component possa receber parâmetros, no caso titulo e url

@Component ({
    moduleId: module.id, // diz que o component está na mesma pasta do module, neste caso, o Angular vai procurar na pasta foto, que contém o component E o module
    selector: 'foto', // o nome da tag html que chama o component
    templateUrl:'./foto.component.html'
})
export class FotoComponent
{
    // titulo e url são parâmetros que recebem valores passados através do selector no html: <foto url="img/leao.jpg" titulo="Leão"></foto>
    @Input() titulo : string;
    @Input() url : string;

    // Descricao não recebe o @Input() pq nesse componente, somente o titulo e a url serão recebidos como parâmetros enviados de outros lugares
    descricao : string;
}

E o componente de cadastro?

Você não inicializou as propriedades com valor default em FotoComponent. Se fizer new FotoComponent() ficarão undefined.

Isso era para ter sido feito antes.

OK.

Fiz a inicialização das propriedades, mas ainda ocorre o problema.

foto.component

import { Component, Input } from '@angular/core'; // Input serve para que o meu component possa receber parâmetros, no caso titulo e url

@Component ({
    moduleId: module.id, // diz que o component está na mesma pasta do module, neste caso, o Angular vai procurar na pasta foto, que contém o component E o module
    selector: 'foto', // o nome da tag html que chama o component
    templateUrl:'./foto.component.html'
})
export class FotoComponent
{
    // titulo e url são parâmetros que recebem valores passados através do selector no html: <foto url="img/leao.jpg" titulo="Leão"></foto>
    @Input() titulo : string = '';
    @Input() url : string = '';

    // Descricao não recebe o @Input() pq nesse componente, somente o titulo e a url serão recebidos como parâmetros enviados de outros lugares
    descricao : string = '';
}

cadastro.component

import { Component } from '@angular/core';
import { FotoComponent } from '../foto/foto.component';
import { Http, Headers } from '@angular/http';
import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // Validação de formulários

@Component ({
    moduleId    : module.id,
    selector    : 'cadastro',
    templateUrl : './cadastro.component.html'
})
export class CadastroComponent 
{
    foto : FotoComponent = new FotoComponent();
    http : Http;
    meuForm : FormGroup

    constructor (http : Http, formBuilder : FormBuilder)
    {
        this.http = http;
        this.meuForm = formBuilder.group ({
            titulo : ['', Validators.compose([Validators.required, Validators.minLength(4)])],
            url : ['', Validators.required],
            descricao : [''] // mesmo a descricao nao sendo required, ela tem de estar no group
        });
    }

    cadastrar (event)
    {
        // Evita que o formulário faça o submit recarregando a página
        event.preventDefault();

        console.log(this.foto);

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');

        // Faz um POST para o servidor, enviando um JSON para lá
        this.http
            .post('v1/fotos', JSON.stringify(this.foto), { headers : headers })
            .subscribe(() => { // () pq o servidor não devolve nada. Caso tivesse alguma resposta, essa resposta seria passada antes do =>
                this.foto = new FotoComponent(); // Cria uma nova foto, vazia. Posi dessa forma, quando voltar pra view do formulário, o formulário não estar preenchido com os dados da última foto cadastrada
                console.log('Foto salva com sucesso');
            }, error => console.log('Ocorreu um erro'));
    }
}

Bom, seu código esta indicando que esta tudo certo, mas você diz que ainda é exibido undefined, certo? Mesmo quando você digita na URL? Por algum motivo que desconheço olhando seu código, a propriedade ainda continua undefined, é como se ela não tivesse adotado o valor padrão. Fez isso com o compilador em tempo real do TypeScript ligado? Se não fizer, não vai adiantar.

Então, parece que era o compilador, que não estava ativado. Porém, com o compilador ativado, aparece o "alt" da imagem.

Link com o print de como fica: https://drive.google.com/open?id=0B3MW4r2fI9TBcER5SWlVMk5Wc0k

Uma dúvida surgiu: fiquei com a impressão agora de que para Angular 2 funcionar corretamente, o compilador de TypeScript deve estar ativado?

Como funciona isso em um ambiente de produção? Quando meu app com Angular estiver no ar, usando Apache e PHP como o back end?

solução!

O resultado do seu código agora é o esperado, funcionou. Vamos aos esclarecimentos meu aluno, para você ficar cangaceiro no assunto.

Você só precisa do compilador do TypeScript em tempo de compilação, enquanto desenvolve. Depois que o projeto estiver pronto, os arquivos compilados são empacotados e colocados em qualquer servidor.

Quando lancei esse curso, o Angular CLI era Beta e BUGADÃO. Mas hoje, se você for criar um projeto do zero, use o Angular CLI. Ele, além de criar um server para desenvolvimento, possui comandos que empacotam sua aplicação. No final, é sempre gerado um arquivo js chamado bundle.js e basta levá-lo como index.html para um servidor web do seu interesse.

Eu amarrei essa explicação muito bem no curso de Vue.js, porque ele já vem com CLI e é bem estável. Pode parecer estranho eu falar isso, mas seria bem interessante que você assistisse os vídeo que vou lhe passar. O conceito é o mesmo com o Angular CLI e o Angular.

https://cursos.alura.com.br/course/vue-parte2/task/23715

Não vai tomar muito o seu tempo, mas vai dar uma clareada muito boa nessa questão.

Aliás, se você não fechou com Angular ainda, talvez dar uma chance para o Vue também seja interessante.

Espero ter ajudado, meu aluno!

Ajudou muito sim!

Obrigado pela dedicação.

Quanto ao Angular vs Vue, estou indo de Angular, pois pretendo depois fazer o curso de Ionic 2.

Mas já ouvi falar bem do Vue tbm.

Obrigado.

Então, vou fazer um spoiler. Em breve teremos um curso só de TypeScript. Esse curso ajudará o aluno nos cursos de Angular, inclusive no curso de Ionic2.

Assim que sair, sugiro cursá-lo para ficar ainda melhor nessas tecnologias.

Quando chegar em Ionic2, verá que muitos dos conceitos que aprendeu no curso do Angular serão aplicados, por isso ele é pré-requisito. Já adianto que no final do curso de Ionic2, eu ensino a migrar para o Ionic3.

Sucesso e bom estudo meu aluno!