2
respostas

Editando um card

Estou gostando muito do curso. Porém, gostaria de incluir um botão de editar uma nota. Como posso fazer isso?

Obrigado

2 respostas

Olá, Ricardo, tudo bem? Desculpe-nos a demora para responder!

Mas vamos lá, até esse momento do curso nós já temos todas as ferramentas necessárias para conseguir fazer o que você está pedindo! Mas existem várias formas diferentes de implementação. Eu pensei em uma forma simples, que pode te guiar para uma mais complexa, caso você queira melhorar depois!

Vamos começar criando um botão "Editar Nota" para cada nota em CardNota.jsx:

  render() {
    return (
      <section className="card-nota">
        <header className="card-nota_cabecalho">
          <h3 className="card-nota_titulo">{this.props.titulo}</h3>
          <DeleteSVG onClick={this.apagar.bind(this)} />
        </header>
        <p className="card-nota_texto">{this.props.texto}</p>
        <button>
          Editar Nota
        </button>
      </section>
    );
  }

O projeto já deve ficar algo assim:

Print do navegador com o projeto, com três cards iguais criados e três categorias criadas. Cada card possui um botão simples com o texto "Editar Nota" logo abaixo da descrição. Cada card tem o título chamado "Título" e a descrição chamada "Descrição".

Agora assim como o SVG de deletar nota, vamos adicionar um evento onClick no botão de editar nota, que chamará uma função chamada editar(). Teremos algo assim:

class CardNota extends Component {

  apagar() {
    const indice = this.props.indice;
    this.props.apagarNota(indice);
  }

  editar() {
    // Código da função...
  }

  render() {
    return (
      <section className="card-nota">
        <header className="card-nota_cabecalho">
          <h3 className="card-nota_titulo">{this.props.titulo}</h3>
          <DeleteSVG onClick={this.apagar.bind(this)} />
        </header>
        <p className="card-nota_texto">{this.props.texto}</p>
        <button onClick={this.editar.bind(this)}>
          Editar Nota
        </button>
      </section>
    );
  }
}

O que eu pensei foi: na função editar(), podemos emitir prompts para o usuário, pedindo o novo título e a nova descrição que a pessoa quer para atualizar a Nota. Além disso, assim como a função apagar(), a função editar() também precisa saber o índice da nota que irá editar. Nossa função ficará assim em CardNota.jsx:

  editar() {
    const indice = this.props.indice;
    const novoTitulo = prompt("Digite o novo título");
    const novoTexto = prompt("Digite a nova descrição");
    this.props.editarNota(indice, novoTitulo, novoTexto);
  }

Note que eu estou escrevendo this.props.editarNota(indice, novoTitulo, novoTexto), mas editarNota é uma propriedade que ainda não existe para o CardNota. Vamos criá-la em ListaDeNotas.jsx:

  render() {
    return (
      <ul className="lista-notas">
        {this.props.notas.map((nota, index) => {
          return (
            <li className="lista-notas_item" key={index}>

              <CardNota 
              indice={index}
              apagarNota={this.props.apagarNota}
              editarNota={this.props.editarNota}  // criando a propriedade "editarNota" para o CardNota
              titulo={nota.titulo} 
              texto={nota.texto}/>
            </li>
          );
        })}
      </ul>
    );
  }

Mas agora a ListaDeNotas também está acessando uma propriedade de mesmo nome que ainda não existe. Vamos criá-la em App.js:

  render() {
    return (
      <section className="conteudo">
        <FormularioCadastro criarNota={this.criarNota.bind(this)} />
        <main className="conteudo-principal">
          <ListaDeCategorias
            adicionarCategoria={this.adicionarCategoria.bind(this)}
            categorias={this.state.categorias}
          />
          <ListaDeNotas
            apagarNota={this.deletarNota.bind(this)}
            editarNota={this.editarNota.bind(this)}  // criando a propriedade "editarNota" para a ListaDeNotas
            notas={this.state.notas}
          />
        </main>
      </section>
    );
  }

Agora falta apenas criarmos o método editarNota() em App.js! Continuarei a resposta no próximo post.

Assim como eu escrevi lá em CardNota.jsx, o método editarNota() deve receber os seguintes parâmetros: índice, novo título e novo texto. Vamos começar a criar o método:

  editarNota(index, titulo, texto) {
    const notaAtualizada = {titulo, texto}
    // Agora devemos atualizar o state com a nota atualizada
  }

Agora falta apenas a lógica para atualizar o state com a notaAtualizada. Será algo semelhante ao que fizemos ao deletar uma nota: vamos copiar o array this.state.notas para um array chamado arrayNotas, fazer a atualização necessária em arrayNotas e depois atualizar o state com esse novo array.

  editarNota(index, titulo, texto) {
    const notaAtualizada = {titulo, texto}
    let arrayNotas = this.state.notas;  // copiamos as notas do state para um novo array
    arrayNotas[index] = notaAtualizada;  // no índice fornecido, sobrescrevemos a nota antiga colocando a "notaAtualizada"
    this.setState({ notas: arrayNotas });  // atualizamos o state com o array modificado
  }

E pronto! Isso já deve estar funcional.

É uma forma mais simples, mas você pode pensar em implementações mais agradáveis para o usuário. Um desafio que deixo para você é: quando a pessoa clicar em um dos botões de editar nota, o formulário poderia entrar em um "modo de edição". Nesse modo, o formulário também poderia ter dois botões "Confirmar" e "Cancelar" para as alterações que a pessoa digitar nos campos. Ao confirmar ou cancelar, o formulário voltaria ao "modo de criar uma nova nota".

Certamente essa é uma forma mais avançada que exigirá que você renderize apenas os componentes desejados dependendo das variáveis do seu state. Você pode criar uma variável no state chamada modoEdicao, por exemplo, que terá valor true ou false. Dependendo dos valores dessa variável, você irá deixar o formulário no "modo de criação" ou no "modo de edição".

Espero ter ajudado! Se tiver mais dúvidas ou dificuldades, estaremos aqui para te auxiliar. Bons estudos! :)