Skip to content

Latest commit

 

History

History
592 lines (433 loc) · 15.5 KB

File metadata and controls

592 lines (433 loc) · 15.5 KB

Sprint 6: Editing and Updating Todos

EditTodoForm Component

  1. Create a new file for an EditTodoForm component. Add a simple form.
// src/components/EditTodoForm.js
import React, {Component} from 'react'

class EditTodoForm extends Component {
  render(){
    return (
      <div className='editTodoForm'>
        <form>
          <input
            placeholder='Write updated todo here...'
            type='text'
            value='' />
          <button type='submit'>Update Todo!</button>
        </form>
      </div>
    )
  }
}

export default EditTodoForm
  1. Import the EditTodoForm component into src/components/Todo.js, and add the EditTodoForm component into the Todo component's render method. Since only one JSX element can be returned, wrap the form and the existing paragraph in a div.
class Todo extends Component {
  render(){
    return(
      <div>
        <p data-todos-index={this.props.todo._id}>
          <span>{this.props.todo.body}</span>
          <span
            className='deleteButton'
            onClick={() => this.props.onDeleteTodo(this.props.todo)}>
              (X)
          </span>
        </p>
        <EditTodoForm />
      </div>
    )
  }
}
  1. Try interacting with the edit forms on the /todos route.

Just like the initial CreateTodoForm, these forms have some problems:

  • They don't allow the user to change the input field.
  • They use the default behavior for form submission (including reloading the page).
  • They aren't connecting the value of the text in the input to any part of the component's props or state.
  1. Update the edit todo form JSX with an onChange attribute for the input element. The onChange should capture the change event and send it to another method of the class.

Also write a simple version of the new method that console.logs a message.

Consider calling the new method onInputChange to match the structure used for CreateTodoForm.

// src/components/EditTodoForm.js
// ...
  onInputChange(event) {
    console.log('changing a todo!')
  }
  render(){
    return (
      <div className='editTodoForm'>
        <form>
          <input
            onChange={event => this.onInputChange(event)}
            placeholder='Write updated todo here...'
            type='text'
            value='' />
// ...
  1. Update the onInputChange event so that it sets a value within the state of the form component.
// src/components/EditTodoForm.js
// ...
  onInputChange(event){
    console.log('changing a todo!')
    this.setState({
      updatedTodoBody: event.target.value
    })
  }
  1. Add a constructor method to initialize the state.
// src/components/EditTodoForm.js
// ...
  constructor(){
    // use Component's constructor
    super()
    // set initial state
    this.state = {
      updatedTodoBody: ''
    }
  }
// ...
  1. Set the value of the input in the edit todo form JSX to this.state.updatedTodoBody.
<input
  onChange={event => this.onInputChange(event)}
  placeholder='Write updated todo here...'
  type='text'
  value={this.state.updatedTodoBody} />
  1. Add an onSubmit attribute to the form element in the EditTodoForm JSX, and create an onFormSubmit method in the class that logs a message to the console instead of submitting the form with the default behavior.
<form onSubmit={event => this.onFormSubmit(event)}>
onFormSubmit(event){
  event.preventDefault()
  console.log('edit todo form submitted')
}
  1. Think critically about the code you just wrote. What will the onFormSubmit function actually need to do? Write a few lines of pseudocode comments to plan what will happen.
click for ideas
  • get the value from the form or from state (the new todo text)
  • send the value "up" to higher components by calling a method from this.props
  • empty out the form value again

  1. Instead of just logging a message, update the onFormSubmit method. It should call a this.props.onUpdateTodo method using the updatedTodoBody from the component's state as an argument. Then, it should reset the updatedTodoBody to an empty string so the form value clears.
onFormSubmit(event){
  event.preventDefault()
  console.log('edit todo form submitted')
  this.props.onUpdateTodo(this.state.updatedTodoBody)
  this.setState({
    updatedTodoBody: ''
  })
}
  1. Check where the TodoForm is rendered in the Todo component. Does the Todo component send through an onUpdateTodo method through props?

Set Up onUpdateTodo Method

The TodosContainer controls the logic for todos, so the code for updating a todo will be added mostly in TodosContainer and then passed down to the TodoForm through props.

  1. Create an updateTodo method in the TodosContainer component class. For now, have it console.log a message.

  2. Think critically about the code you'll write, and add a few lines of pseudocode in comments. What will the updateTodo method need to do?

click for some ideas
  • have access to the id of the todo that needs to be updated

  • have access to the new information for the todo being updated

  • call a method in the TodoModel class that sends the AJAX request for super-crud to modify the todo

  • update this.state.todos based on the API response

  1. When TodosContainer renders the TodoList component, pass through the updateTodo method as an onUpdateTodo prop. Remember to bind the this from TodosContainer.

  2. In TodoList, when rendering the Todo component, pass through the this.props.onUpdateTodo method as an onUpdateTodo prop.

  3. In Todo, when rendering the EditTodoForm component, pass through the this.props.onUpdateTodo method as an onUpdateTodo prop.

  4. Try submitting the form again. If all elements are connected correctly, the log message from updateTodo in TodosContainer will appear in the console.

Fill in AJAX Call to Update Todo

  1. Add a method to the TodoModel class that makes an AJAX call to update a todo through the super-crud API.

Hint: reference jQuery $.ajax documentation, super-crud documentation, and the other methods in the TodoModel class.

Hint: This method will need to take in the new body for the todo as well as the id of the todo you're updating.

  1. Now that the TodoModel has an update method, fill in the TodosContainer's updateTodo method.

The updateTodo method will also need the updated body and the id for the todo, so you may need to modify the structure to have both of those parameters.

Remember to modify the item(s) in this.state.todos to match the updated information once the API response comes back.

You should see an error if you try to submit the form. It won't work until you're actually passing the id data through from the EditTodoForm.

  1. In order for the EditTodoForm to call the new updateTodo method, it will need access to the _id of each todo. First, add the todo as a prop for EditTodoForm when rendering the EditTodoForm from the Todo class.

  2. In the EditTodoForm JSX, add data-todo-id to the div:

<div className='editTodoForm' data-todos-index={this.props.todo._id}>
  1. Modify the EditTodoForm class's onFormSubmit method to send the updated todo body and the todo id to this.props.onUpdateTodo.

  2. Check the behavior of the edit form now. It should work!

If you have problems, remember the solutions are available.

One last step!