- 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
- Import the
EditTodoForm
component intosrc/components/Todo.js
, and add theEditTodoForm
component into theTodo
component'srender
method. Since only one JSX element can be returned, wrap the form and the existing paragraph in adiv
.
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>
)
}
}
- 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
orstate
.
- Update the edit todo form JSX with an
onChange
attribute for the input element. TheonChange
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.log
s a message.
Consider calling the new method
onInputChange
to match the structure used forCreateTodoForm
.
// 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='' />
// ...
- 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
})
}
- Add a
constructor
method to initialize the state.
// src/components/EditTodoForm.js
// ...
constructor(){
// use Component's constructor
super()
// set initial state
this.state = {
updatedTodoBody: ''
}
}
// ...
- Set the
value
of the input in the edit todo form JSX tothis.state.updatedTodoBody
.
<input
onChange={event => this.onInputChange(event)}
placeholder='Write updated todo here...'
type='text'
value={this.state.updatedTodoBody} />
- Add an
onSubmit
attribute to the form element in theEditTodoForm
JSX, and create anonFormSubmit
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')
}
- 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
- Instead of just logging a message, update the
onFormSubmit
method. It should call athis.props.onUpdateTodo
method using theupdatedTodoBody
from the component's state as an argument. Then, it should reset theupdatedTodoBody
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: ''
})
}
- Check where the
TodoForm
is rendered in theTodo
component. Does theTodo
component send through anonUpdateTodo
method through props?
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.
-
Create an
updateTodo
method in theTodosContainer
component class. For now, have itconsole.log
a message. -
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
-
When
TodosContainer
renders theTodoList
component, pass through theupdateTodo
method as anonUpdateTodo
prop. Remember tobind
thethis
fromTodosContainer
. -
In
TodoList
, when rendering theTodo
component, pass through thethis.props.onUpdateTodo
method as anonUpdateTodo
prop. -
In
Todo
, when rendering theEditTodoForm
component, pass through thethis.props.onUpdateTodo
method as anonUpdateTodo
prop. -
Try submitting the form again. If all elements are connected correctly, the log message from
updateTodo
inTodosContainer
will appear in the console.
- 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 theTodoModel
class.
Hint: This method will need to take in the new
body
for the todo as well as theid
of the todo you're updating.
- Now that the
TodoModel
has anupdate
method, fill in theTodosContainer
'supdateTodo
method.
The
updateTodo
method will also need the updatedbody
and theid
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 theEditTodoForm
.
-
In order for the
EditTodoForm
to call the newupdateTodo
method, it will need access to the_id
of each todo. First, add thetodo
as a prop forEditTodoForm
when rendering theEditTodoForm
from theTodo
class. -
In the
EditTodoForm
JSX, adddata-todo-id
to thediv
:
<div className='editTodoForm' data-todos-index={this.props.todo._id}>
-
Modify the
EditTodoForm
class'sonFormSubmit
method to send the updated todo body and the todo id tothis.props.onUpdateTodo
. -
Check the behavior of the edit form now. It should work!
If you have problems, remember the solutions are available.