1

I am working on developing a UI in react js where i am generating a dynamic table from the data i get from the API, on the left side i have check boxes and each check box have a particular input of type text, which are dynamically generated as stated. What i want to archive is as soon as user check box is checked i need to generate an object which has following 4 fileds isChecked (to check wheather the check box is checked or not), module_id (if checked than i need to get the module id), isUpdated (this is for tracking any changes made on the specific input text, if not it should be zero ), discount_price (if isUpdated is true than i need this value). these things i am trying to achieve by setState in react js.

The necessity for the above defined object is for handling the data in back-end. Based on the conditions i ll be writing the queries, i hope i am clear with my statement problem.

I have initialized the object state in constructor of the class component, i have binded the handleChange method in with both inputs of checkbox and text, but i am getting error like TypeError: Cannot read property 'checked' of undefined, i want to know the best approach of handling such dynamic forms.

constructor(){
    super();
    this.state = {moduleData: [], modules : [] }
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

this is my handleChange function

handleChange(event) {
    const key = event.target.dataset.moduleindex;
    const modId =  event.target.dataset.moduleid;
    const inputKeyType = event.target.type;
    var is_updated = 1;
    if(inputKeyType == 'checkbox'){
      var inputChecked = !this.state.modules[key].checked;
      if (!this.state.modules[key].checked == false) {
        is_updated = 0;
      }
    } else {
      var inputChecked = true;
      is_updated = 1;
    }

    this.setState({
      modules: {
        ...this.state.modules,
        [key]: {
          ["isChecked"]: inputChecked,
          ["module_id"]: modId,
          ["isUpdated"]: is_updated,
          ["discount_price"]: event.target.value,
        }
      }
    });

  }

and this the table which is generated dynamically

const moduleRow =  modules.map((module, index) => (
    <tr key={module.id.toString()}>
              <th scope="row" width="" className='text-center' >
                <Input type="checkbox"
                className="checkbox"
                name="module_id"
                data-moduleindex = {index}
                data-moduleid = {module.id}
                checked={
                  this.state.modules[index]
                    ? this.state.modules[index].checked
                    : ""
                }
                onChange={this.handleChange}
                />
              </th>

              <td>
                {module.module_name}
              </td>

              <td>
                {module.module_short_code}
              </td>

              <td>
                {module.limits}
              </td>

              <td>
                { module.subscriptionInterval === 'monthly' ?  module.monthly_price  : module.annual_price }
              </td>

              <td>
                <Input
                type="text"
                name="discount_price"
                data-moduleindex = {index}
                id = {module.id}
                onChange={this.handleChange}
                value={
                  this.state.modules[index]
                    ? this.state.modules[index].discount_price
                    : ""
                }
                />
              </td>

              <td>
                {this.getStatus(module.status)}
              </td>

            </tr>
          ));

finally i want to get the array of objects like this

[
  0:{"isChecked":true, "module_id":2, "isUpdated" : 1, "discount_price": 5 },
  1:{"isChecked":false, "module_id":3, "isUpdated" : 1, "discount_price": 5 },
  2: {"isChecked":true, "module_id":8, "isUpdated" : 0, "discount_price": "" }
  ]

can this be achieved or am i missing some thing? pls help

1 Answer 1

1

Your problem is here;

if(inputKeyType == 'checkbox'){
  var inputChecked = !this.state.modules[key].checked;
  if (!this.state.modules[key].checked == false) {
    is_updated = 0;
  }
} 

this.state.modules will be an empty array on initialisation. You are using checked rather than isChecked. All checkboxes start as false so something like;

if(inputKeyType === 'checkbox'){
  var inputChecked = this.state.modules[key] ? !this.state.modules[key].isChecked : true
  if (inputChecked === false) {
    is_updated = 0;
  }
} else {
  var inputChecked = true;
  is_updated = 1;
}

this.state.modules also starts as an array, and you end up assigning it as an object in setState. So in your constructor I would make modules initialised as an empty object

And also in the input type need to do this

 <Input type="checkbox"
                className="checkbox"
                name="module_id"
                data-moduleindex = {index}
                data-moduleid = {module.id}
                checked={
                  this.state.modules[index]
                    ? this.state.modules[index].isChecked
                    : ""
                }
                onChange={this.handleChange}
                />
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for the help, it really helped me to solve some of the issue, now i am able to get the exact data, will except your answer once i solve it.

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.