Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to get form values in React-Bootstrap's Formgroup Component

I am using React-Bootstrap and I want to get the values of an input form so that I can save them to Firebase. Before using React-Bootstrap, I was able to grab the value of an input and the text area by using ref, but now I am not able to do that after usingFormGroups`. Upon submitting the form, I am unable to grab the values from the input and the text area.

I've seen previous post concerning this problem, but it seems none these solutions actually work.

I am new to React. Can someone please explain to me how to grab form values from using Formgroups?

import React from 'react'
import ReactDOM from 'react-dom'
import {withRouter} from 'react-router'
import './NewListPage.css'
import Header from './Header'
import ListItem from './ListItem'
import database from '../database'
import Form from './Form'
import {
  Button,
  FormGroup,
  FormControl,
  Feedback,
  ControlLabel
} from 'react-bootstrap';

class NewListPage extends React.Component {
  // bring props into constructor
  constructor(props) {
    // bring props into super
    super(props)
    //create list uuid this needs to be A better uuid genereator in the future
    const listId = Math.floor((Math.random() * 10000) + 1)
    this.state = {
      wishList: {
        items: []
      },
      wishListItems: []
    }
    this.addListItem = this.addListItem.bind(this) //bind the add list item function to this component
    this.removeListItem = this.removeListItem.bind(this) //needed to bind update order to root class
    this.saveListItem = this.saveListItem.bind(this) //bind to root class
  }

  addListItem(e) { //add another item to the array
    e.preventDefault()
    // never change state directly, make a copy instead
    const wishList = Object.assign({}, this.state.wishList)
    //push a new item to items object
    wishList.items.push({title: 'title', description: 'description'})
    this.setState({
      //update the state
      wishList
    })
  }

  // remove items from array
  removeListItem(index) {
    // never change state directly, make a copy instead
    const wishList = Object.assign({}, this.state.wishList)
    //remove item object from items array using its index
    wishList.items.splice([index], 1)
    this.setState({
      //update the state from the new array
      wishList
    })
  }

  // save list item into dB
  saveListItem(event) {
    // upon submit, prevent whole page from refreshing
    event.preventDefault()
    // never change state directly, make a copy instead
    const wishList = Object.assign({}, this.state.wishList)
    // grab the title
    wishList.title = this.refs.title.value
    // grab the description
    wishList.description = this.refs.description.value
    // for each item in the list grab its properties
    wishList.items.map((item, index) => {
      // grab descritions and title from generated form
      item.description = this.refs.list.children[index].children.itemdescription.value
      item.title = this.refs.list.children[index].children.itemtitle.value
    })
    // push the wishlist to firebase (need to add code to handle errors.)
    // we use push so that firebase will generate its own uuid
    database.push('wishLists', {
      data: wishList
      // if it saves then resolve this promise and push the uuid to users/uid/wishLists
    }).then(newList => {
      database.push(`users/${this.props.currentUser.uid}/wishLists`, {
        // newList.key contains the firebase uuid from the previous push
        data: newList.key
        // if this also saves then redirect
      }).then(finished => {
        //redirect to dashboard
        this.props.history.push('/')
      })
    })
  }

  render() {
    return (
      <div>
        <h1>Create a New Wishlist</h1>
        <div className="ListForm">
          <Row>
            <Col sm={3}/>
            <Col sm={6}>
              <form onSubmit={this.saveListItem.bind(this)}>
                <FormGroup>
                  <ControlLabel>Wishlist Title</ControlLabel>
                  <br/>
                  <FormControl type="text" name="title"  ref="title" required="true" placeholder="Enter text"/>
                  <FormControl.Feedback/>
                  <br/>
                  <FormGroup controlId="formControlsTextarea">
                    <ControlLabel>Wishlist Description Optional</ControlLabel>
                    <FormControl componentClass="textarea" placeholder="textarea" name="description" ref="description"/>
                  </FormGroup>
                  <br/>

                  <div className="ListItems" ref="list">
                    {this.state.wishList.items.map((item, index) => {
                      return <ListItem removeListItem={this.removeListItem} myIndex={index} key={index}/>
                    })}
                  </div>
                  <Button bsStyle="primary" type="button" onClick={this.addListItem}>ADD ITEM</Button><br/><br/>
                  <input type="submit" value="Save List" ref="save"/>
                </FormGroup>
              </form>
            </Col>
          </Row>
        </div>
      </div>
    )
  }
}
// export with router
export default withRouter(NewListPage)

Here is the error message from the window console log.

      • enter image description here
like image 314
Abulurd Avatar asked May 30 '17 08:05

Abulurd


1 Answers

It's because your ref is no longer an <input> DOM node, but a React Bootstrap <FormControl> instance.

Use form.elements instead to get a hold of the form's inputs by their name:

let form = event.target
wishlist.title = form.elements.title.value
wishlist.description = form.elements.description.value
like image 197
Jonny Buchanan Avatar answered Oct 27 '22 11:10

Jonny Buchanan