3

I'm soooo close to getting this to work but just can't seem to wrap my head around this.

I have a form that's supposed to submit to a json file with the following structure:

    {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }

I'm able to set the state for the title no problem, as well as the first object in the content array. I think I need to create a loop or something? Below is my full component.

import React, { Component } from 'react';

class AddEditPage extends Component {
  constructor(props) {
    super(props)
    this.state = {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }
    this.addInput = this.addInput.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleNestedChange = this.handleNestedChange.bind(this);
  }

  handleChange(e) {
    const value = e.target.value
    this.setState({
      [e.target.name]: value
    })
  }

  handleNestedChange(e) {
    const value = e.target.value
    console.log(e.target.id)
    this.setState({

    })

  }

  handleSubmit(e) {
    e.preventDefault();
    console.log(this.state)
  }

  addInput() {
    const newInput = { className: '', body: ''}
    this.setState({content: this.state.content.concat(newInput)});
  }


  render() {
    const contentInputs = this.state.content.map((content, i)=> {
     return (
        <div key={i}>
          <input 
            type="text" 
            name="className"
            id={`${i}`} 
            placeholder="Class name"
            onChange={this.handleNestedChange}
          />
          <input 
            type="text" 
            name="body" 
            placeholder="Body"
            id={`${i}`}
            onChange={this.handleNestedChange}
          />
        </div>
      )
    })

    return (
      <div>
        <h2>New Page</h2>
        <form onSubmit={this.handleSubmit}>
            <input 
            type="text" 
            name="title" 
            placeholder={this.state.title || `Enter the title`}
            onChange={this.handleChange} 
            />
          <h3>Content</h3>
            {contentInputs}
            <button onClick={this.addInput}>Add</button>
          <input type="submit" />
        </form>
      </div>
    );
  }
}

export default AddEditPage;

🍩 & praise for the answer haha

2
  • What exactly is your issue? One thing to note is the way you have addInput, state.content will never grow (I believe). Try using push instead, ie, let newValues = this.state.content.push(newInput) then this.setState({ content: newValues }); Commented Jul 5, 2017 at 15:30
  • @terpinmd adding the inputs work great. It's setting the state part for the nested inputs that im having issues with Commented Jul 5, 2017 at 15:35

2 Answers 2

0

Although it's not a very robust solution, assuming the input 'name' attributes always match exactly to the object keys in your state, you can do this:

handleNestedChange(e) {
    const newStateContent = this.state.content;
    newStateContent[e.target.id][e.target.name] = e.target.value;
    this.setState({
      content: newStateContent
    });
}
Sign up to request clarification or add additional context in comments.

Comments

0

I think handleNestedChange is not binded properly, because the context this is refering to map function not the component. You have to bind map function with current context.

const contentInputs = this.state.content.map((content, i)=> { 
    return ( 
    <div key={i}> <input type="text" name="className" id={`${i}`} placeholder="Class name" onChange={this.handleNestedChange} /> <input type="text" name="body" placeholder="Body" id={`${i}`} onChange={this.handleNestedChange} /> </div> 
) 
}).bind(this)

Comments

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.