Skip to content
This repository has been archived by the owner on Jun 7, 2019. It is now read-only.

08 Creación de listas

Jorge Bejar edited this page May 28, 2018 · 15 revisions

Creamos el componente NewList

Creamos el archivo src/components/NewList.js, cuyo contenido debería ser el siguiente:

import React, { Component } from 'react';

class NewList extends Component {
  render() {
    return (
      <div className="NewList">
        <a className="NewList-placeholder">Add a list…</a>
      </div>
    );
  }
}

export default NewList;

Invocamos el componente NewList en el componente Board:

Para ello editamos src/components/Board.js, importando el componente:

  import React, { Component } from 'react';
  import ListTile from './ListTile';
+ import NewList from './NewList';

Y luego invocándolo:

 render() {
    return (
      <div className="Board">
        <div className="Board-content">
          <div className="Board-header">
            <span className="Board-header-btn">
              {this.state.name}
            </span>
          </div>

          <div className="Board-canvas">
            <div className="Board-canvas-content">
              {
                this.state.lists.map((list) => {
                  return <ListTile key={list.id} id={list.id} name={list.name} boardId={this.boardId} cards={list.cards}/>
                })
              }
+             <NewList boardId={this.boardId} />
-             <div className="NewList">
-               <a className="NewList-placeholder">Add a list…</a>
-             </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

Formulario de creación de listas

A continuación, vamos a agregar un formulario al componente recién creado, que nos permita agregar nuevas listas al mismo.

Para ello, primero modificaremos nuestro componente src/components/NewList.js de la siguiente forma:

render() {
  return (
    <div className="NewList">

      // ###### Agregar: COMIENZO bloque
      <div className="NewList-adding-list">
        <form>
          <input className="NewList-input" type="text" placeholder="Add a list…" autoFocus="true"/>
          <div className="NewList-controls">
            <input className="NewList-button" type="submit" value="Save"/>
            <div className="NewList-close"/>
          </div>
        </form>
      </div>
      // ###### Agregar: FIN bloque

      <a className="NewList-placeholder">Add a list…</a>
    </div>
  );
}

Veamos como se ve nuestra aplicación hasta el momento:

list-creation

NOTA: Deberíamos ver tanto el formulario como el link para agregar nuevas listas :)

Ahora, vamos a actualizar nuestro componente para que se muestre o el formulario de agregar una nueva lista, o el link que habilitaría dicho formulario. Para esto, definiremos una propiedad en nuestro componente para indicar si se está agregando o no una nueva lista:

class NewList extends Component {
  // ###### Agregar: COMIENZO bloque
  constructor(props) {
    super(props);
    this.state = {
      composing: false,
      newListName: ''
    };
  }

  toggleComposing = () => {
    this.setState(prevState => ({
      composing: !prevState.composing
    }));
  }
  // ###### Agregar: FIN bloque
 
  render() {
    return (
      <div className="NewList">
        // ###### Quitar: COMIENZO bloque
        <div className=“NewList-adding-list>
          <form>
            <input className="NewList-input" type="text" placeholder="Add a list…" autoFocus="true"/>
            <div className="NewList-controls">
              <input className="NewList-button" type="submit" value="Save"/>
              <div className="NewList-close"/>
            </div>
          </form>
        </div>
        
        <a className=“NewList-placeholder”>Add a list…</a>
        // ###### Quitar: FIN bloque

        // ###### Agregar: COMIENZO bloque
        { this.state.composing ?
          <div className="NewList-adding-list">
            <form>
              <input className="NewList-input" type="text" placeholder="Add a list…" autoFocus="true"/>
              <div className="NewList-controls">
                <input className="NewList-button" type="submit" value="Save"/>
                <div className="NewList-close" onClick={this.toggleComposing}/>
              </div>
            </form>
          </div>
        :
          <a className="NewList-placeholder" onClick={this.toggleComposing}>Add a list…</a>
        }
        // ###### Agregar: FIN bloque
      </div>
    );
  }

🎬 Nuestro toggle debería funcionar de la siguiente manera: gif-toggle-composing-lists

Finalmente, implementamos el método que realmente agrega la nueva lista a nuestro board, una vez presionado el botón "Save":

 class NewList extends Component {
   ...
 
  toggleComposing = () => {
    ...
  }

  // ###### Agregar: COMIENZA bloque
  newListNameChange = (e) => {
    this.setState({
      newListName: e.target.value
    });
  }

  handleSubmit = (e) => {
    e.preventDefault();

    fetch(`/boards/${this.props.boardId}/lists`, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        list: {
          name: this.state.newListName
        }
      }),
    }).then(res => res.json()).then((list) => {
      this.setState({
        composing: false,
        newListName: ''
      })
    });
  }
  // ###### Agregar: FIN bloque

  render() {
    ...
  }

Por último actualizamos la función render para manejar el submit del formulario:

   render() {
     return (
       <div className="NewList">
         {
           this.state.composing ?
             <div className="NewList-adding-list">
-              <form>
+              <form onSubmit={this.handleSubmit}>
-                <input className="NewList-input" type="text" placeholder="Add a list…" autoFocus="true"/>
+                <input className="NewList-input" type="text" placeholder="Add a list…" autoFocus="true" value={this.state.newListName} onChange={this.newListNameChange}/>
                 <div className="NewList-controls">
                   <input className="NewList-button" type="submit" value="Save"/>
                   <div className="NewList-close" onClick={this.toggleComposing}></div>
                 </div>
               </form>
             </div>
           :
             <a className="NewList-placeholder" onClick={this.toggleComposing}>Add a list…</a>
         }
       </div>
     );
   }

Probamos en el browser:

list-creation

Refrescamos el componente padre luego de agregar una nueva lista

Para esto, primero definiremos el método que agrega una nueva lista al estado del componente Board. Luego, lo pasamos como propiedad del componente NewList, para que el mismo nos pueda notificar cuando una nueva lista sea agregada al Board.

Modificamos src/components/Board.js:

  constructor(props) {
    super(props);
    this.state = { name: "", lists: [] };
    this.boardId = this.props.match.params.boardId;
  }

  componentDidMount() {
    fetch(`/boards/${this.boardId}`).then(res => res.json()).then((board) => {
      this.setState({
        name: board.name,
        lists: board.lists
      });
    });
  }

+ handleAddList(list) {
+   this.setState(prevState => ({
+     lists: [...prevState.lists, list]
+   }));
+ }
+
  render() {
    return (
      <div className="Board">
        <div className="Board-content">
          <div className="Board-header">
            <span className="Board-header-btn" href="#">
              {this.state.name}
            </span>
          </div>

          <div className="Board-canvas">
            <div className="Board-canvas-content">
              {
                this.state.lists.map((list) => {
                  return <ListTile id={list.id} name={list.name} key={list.id} boardId={this.boardId} cards={list.cards}/>
                })
              }
-             <NewList boardId={this.boardId}/>
+             <NewList boardId={this.boardId} onListCreation={this.handleAddList.bind(this)}/>
            </div>
          </div>
        </div>
      </div>
    );
  }

Agregamos la siguiente línea en src/components/NewList.js para notificar sobre la creación de la nueva lista:

handleSubmit = (e) => {
  e.preventDefault();

  fetch(`/boards/${this.props.boardId}/lists`, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      list: {
        name: this.state.newListName
      }
    }),
  }).then((res) => { return res.json(); }).then((list) => {
+   this.props.onListCreation(list);
    this.setState({
      composing: false,
      newListName: ''
      })
  });
}

Commit en git

git add -A
git commit -m "Creación de listas"

Siguiente: Bonus track - Agregar Tests

# Agregar el remote si no se hizo antes
git remote add origin https://github.com/wyeworks/react-workshop-2018.git
git fetch origin
# Fin paso opcional

git reset --hard ee3cac8