0

I've created a React app for a school project that can add multiple types of input fields to a view by clicking a button (sort of like Wordpress Gutenberg).

Currently, I can add one of each type of item onto the view. However, if I click the button again, it erases the current text that was added. I'd like the ability to click the button to add as many fields as I'd like on click.

Also, the items are only added into the view in the order they were created meaning, even if I choose photo first and I click headline after, it (headline) will appear at the top of the list above the initial item.

I've had a look at these solutions (which were pretty good) but they didn't provide what I need.

Dynamically adding Input form field issue reactjs

and "update delete list elements using unique key": https://www.youtube.com/watch?v=tJYBMSuOX3s which was closer to what I needed to do.

Apologies in advance for the length of the code,(there are two other related components for text input and an editform). I'm sure there is a much more simple way to do this. I haven't been able to find an npm package or solution to this specific problem online and am open to a simpler solution.

Edit.jsx

export default class Edit extends React.Component {
  state = {
    texts: {
      hl: '',
      shl: '',
      txt: '',
      photo: []
    },
    coms: {
      hl: false,
      shl: false,
      txt: false,
      photo: null
    },
    labels: {
      // Replace with icons
      hl: 'Headline',
      shl: 'Sub',
      txt: 'Text Area',
      photo: 'Photo'
    },
    selectedItem: '',
  }




  componentDidMount() {
    const saveData = localStorage.getItem('saveData') === 'true';
    const user = saveData ? localStorage.getItem('user') : '';
    this.setState({ user, saveData });
  }

  createPage = async () => {
    await this.props.postPage(this.state.texts)
  }

  // add options
  addOptions = (item) => {
    const { coms } = this.state
    coms[item] = !coms[item]
    this.setState({ coms: coms })
  }

  // ADD TEXT
  addTxt = () => {
    this.setState({ texts: [...this.state.texts, ""] })
  }

  enableAllButtons = () => {
    this.setState({ selectedItem: '' })
  }

  handleChange = (e, index) => {
    this.state.texts[index] = e.target.value
    //set the changed state.
    this.setState({ texts: this.state.texts })
  }

  setDisable = (selectedItem) => {
    this.setState({ selectedItem })
  }

  handleRemove = () => {
    // this.state.texts.splice(index, 1)
    this.setState({ texts: this.state.texts })
  }

  handleSubmit = (e) => {
    console.log(this.state, 'all text')
  }

  handleChange = (e, item) => {
    let { texts } = this.state
    texts[item] = e.target.value
    //set the changed state.
    this.setState({ texts })
    console.log(texts)
  }

  render() {
    const { coms, labels, selectedItem, texts } = this.state
    let buttons = Object.keys(coms)
    let showItems = Object.keys(coms).filter(key => coms[key] === true)

    return (
      <div>
        <InnerHeader />
        {/* Make a route for edit here */}
        <Route path='/edit/form' render={() => (
          <EditForm
            texts={texts}
            coms={coms}
            labels={labels}
            addOptions={this.addOptions}
            setDisable={this.setDisable}
            selectedItem={selectedItem}
            showItems={showItems}
            handleChange={this.handleChange}
            enableAllButtons={this.enableAllButtons}
          />
        )} />

        {/* Make route for preview */}
        <Route path='/edit/preview' render={(props) => (
          <Preview
            {...props}
            createPage={this.createPage}
          />
        )}
        />
      </div>
    )
  }
}

AddText.jsx:


export default class AddText extends Component {

  state = {
  }

  // ADD TEXT
  addTxt(item) {
    const {
      addOptions } = this.props
    addOptions(item)
  }


  render() {
    const { coms, labels } = this.props
    const { selectedItem } = this.props
    let buttons = Object.keys(coms)
    console.log('here', selectedItem)
    return (
      <div>

        <Card>
          <Card.Body>
            {

              buttons.map((item, index) => <button
                value={(selectedItem === "") ? false : (selectedItem === item) ? false : true} key={index} onClick={() => this.addTxt(item)}>
                {labels[item]}
              </button>
              )
            }
          </Card.Body>
        </Card>
      </div>
    )
  }
}

EditForm.jsx


export default function EditForm(props) {
  return (
    <div>

      <div className='some-page-wrapper-sm'>
        <div className="dash-card-sm">
          <button><Link to={{
            pathname: '/edit/preview',
            item: props.texts
          }}>preview</Link></button>
          <br />
          <br />
          <AddText
            coms={props.coms}
            labels={props.labels}
            addOptions={props.addOptions}
            setDisable={props.setDisable}
            selectedItem={props.selectedItem}
          />
          <div>
            {
              props.showItems.map((item, index) => {
                return (

                  <InputFieldComponent
                    // setDisable={props.setDisable}
                    onChangeText={(e) => props.handleChange(e, item)}
                    enableAllButtons={props.enableAllButtons}
                    key={index}
                    item={item}
                    labels={props.labels}
                    texts={props.texts}
                  />
                )
              })
            }
          </div>
        </div>
      </div>
    </div>
  )
}

InputFieldComponent.jsx


export default class InputFieldComponent extends React.Component {


  setWrapperRef = (node) => {
    this.wrapperRef = node;
  }



  render() {
    const { labels, item, onChangeText, texts } = this.props
    return (
      <div>
        <textarea
          className="txt-box"
          ref={this.setWrapperRef}
          onChange={onChangeText}
          placeholder={labels[item]}
          value={texts[item]} />
      </div>
    )
  }
}
4
  • 1
    can you create a Sandbox? and maybe will be easier to help/debug there Commented Oct 3, 2019 at 16:08
  • 1
    I agree with @RicardoGonzalez. It looks like there's some code missing since you state you have input fields and I'm not seeing the input fields. I kinda feel like you have an issue where the name or id of the fields are all the same value and the browser is clearing the existing fields when you set the new input fields with the value of "". Commented Oct 3, 2019 at 16:13
  • 1
    Hi @RicardoGonzalez, I've added the full code including the other two components. I'm not sure how I'd add this to a sandbox since it's tied in with an auth system. Commented Oct 3, 2019 at 16:40
  • 1
    Great @RHBlanchfield i will check it ! Commented Oct 3, 2019 at 16:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.