I'm trying to pre-populate a form using the redux-form library. The issues I'm having now is being able to pass (perhaps) the item.id
from the Items
or Item
component to the List
when the Edit Item
button is clicked. That way I could check it against my listItems
array and grab it's data to populate the form. But prior to doing this, I created a function populateForm
to try redux-form's dispatch/initialize
function for "populating
" the form. It works as expected, except that when I click Add Item
the form never resets. I basically need two things done.
- Get the logic going for selecting a single item and get it's data populated in the form so it can be edited.
- figure why the form doesn't reset after it's populated on
Edit Item
click.
Thanks in advance.
/components/List.jsx
export class List extends React.Component {
constructor(props) {
super(props)
this.state = {
isModalOpen: false
}
this.resetFrom = this.resetForm.bind(this)
}
toggleModal () {
this.setState({ isModalOpen: !this.state.isModalOpen })
}
deleteList (listId, e) {
e.stopPropagation()
this.props.listActions.deleteList(listId)
}
resetForm() {
this.props.reset('items')
}
createItem (item) {
let items = {
id: uuid.v4(),
sku: item.sku,
text: item.text,
price: item.price
}
this.props.itemActions.createItem(items)
this.props.listActions.connectToList(this.props.list.id, items.id)
this.resetForm()
}
// UPDATED
populateForm (item) {
const { id, sku, text, price } = item
this.props.dispatch(initialize('items', {
id, sku, text, price
}, ['id', 'sku', 'text', 'price']))
}
// WAS THIS
//populateForm () {
//this.props.dispatch(initialize('items', {
//sku: "Stuff",
//text: "blah",
//price: "this"
//}, ['sku', 'text', 'price']))
//}
render () {
const { list, ...props } = this.props
const listId = list.id
return (
<div {...props}>
<div className='list-add-item'>
<button onClick={this.toggleModal.bind(this, listId)}>+</button>
</div>
<div className='list-header'
onClick={() => props.listActions.updateList({id: listId, isEditing: true})} >
<Editor
className='list-title'
isEditing={list.isEditing}
value={list.title}
onEdit={(title) => props.listActions.updateList({id: listId, title, isEditing: false})}>
</Editor>
<div className='list-delete'>
<button onClick={this.deleteList.bind(this, listId)}>x</button>
</div>
</div>
<Items
items={props.listItems}
// UPDATED
populateForm={(item) => this.populateForm(item)}
// WAS THIS
// populateForm={(id) => this.populateForm({id, isEditing: true})}
openModal={this.toggleModal.bind(this)}>
</Items>
<Modal
className='list-add-item'
openModal={this.state.isModalOpen}>
// UPDATED
<ItemForm
onEdit={this.props.itemActions.updateItem}
onSubmit={this.createItem.bind(this)}>
</ItemForm>
// WAS THIS
// <ItemForm onSubmit={this.createItem.bind(this)}/>
</Modal>
</div>
)
}
}
function mapStateToProps (state, props) {
return {
lists: state.lists,
listItems: props.list.items.map((id) => state.items[
state.items.findIndex((item) => item.id === id)
]).filter((item) => item)
}
}
function mapDispatchToProps (dispatch) {
return {
listActions: bindActionCreators(listActionCreators, dispatch),
itemActions: bindActionCreators(itemActionCreators, dispatch),
reset: bindActionCreators(reset, dispatch),
dispatch: bindActionCreators(dispatch, dispatch)
}
}
const { string, arrayOf, shape } = React.PropTypes
List.propTypes = {
lists: arrayOf(shape({
id: string.isRequired,
title: string.isRequired
}).isRequired)
}
export default connect(mapStateToProps, mapDispatchToProps)(List)
/components/Items.jsx
export default class Items extends React.Component {
render () {
const {items, openModal, populateForm, ...props} = this.props
return (
<ul className='items'>{items.map((item) =>
<Item
className='item'
key={item.id}
id={item.id}
sku={item.sku}
text={item.text}
price={item.price}
// UPDATED
populateForm={populateForm.bind(null, item)}
// WAS THIS
// populateForm={populateForm.bind(this)}
openModal={openModal}>
</Item>
)}</ul>
)
}
}
/components/Item.jsx
export default class Item extends React.Component {
render () {
const { openModal, populateForm, ...props } = this.props
return (
<span>
<li>SKU: {this.props.sku}</li>
<li>ITEM: {this.props.text}</li>
<li>PRICE: {this.props.price}</li>
<button onClick={this.props.populateForm}>Edit Item</button>
</span>
)
}
}
/components/ItemForm.jsx
import React from 'react'
import { reduxForm } from 'redux-form'
class ItemForm extends React.Component {
render() {
const { fields: {sku, text, price}, handleSubmit } = this.props
return (
<form onSubmit={handleSubmit} >
<label>SKU</label>
<input type="text" {...sku}/>
<label>Item</label>
<input type="text" {...text} />
<label>Price</label>
<input type="text" {...price} />
<button type="submit">Add item</button>
</form>
)
}
}
ItemForm = reduxForm({
form: 'items',
fields: ['sku', 'text', 'price']
})(ItemForm);
export default ItemForm
There are several problems that make this code hard to follow for me. I'm not really sure what you're trying to accomplish. For example:
List.jsx
is callingpopulateForm()
with{id, isEditing: true}
, butpopulateForm()
doesn't take any parameters.For some reason
Items.jsx
is bindingpopulateForm
tothis
. Why?Item.jsx
is passingpopulateForm
directly toonClick
, so its parameter is going to be the event.ItemForm.jsx
, in contrast, is flawless.