1

I have a dynamic form with the following implementation. The problem is that I want to "check" the checkbox IF the answer of that "questionID" exists in the answers array with the selected option (i.e A,B). so the condition of the check should be answers[index].userChoice.option is equal to Object.keys(x). enter image description here

import fieldsL from "./fields.json"; 

function App() { 
  let [Fields , setFields] = useState([]);
  let [answers, setAnswers] = useState([]);
const updateAnswer = ((qid,option,optionValue) => {
      let ans = answers;
      let singleAns = {
        questionId : qid,
        userChoice: 
        { 
          option: option, 
          optionValue: optionValue, 
          isChecked: true
        }
      };
      if(answers.length > Fields) return console.warn("Invalid Question ID")
      if(answers.find((sp) => sp.questionId === qid)) {
        var index = answers.map(function(x1) {return x1.questionId}).indexOf(qid);
        answers[index].userChoice.option = option;
        answers[index].userChoice.optionValue = optionValue;
        console.log("Existing Answer Updated");
      }
      else ans.push(singleAns)
      ans.sort((a, b) => parseFloat(a.questionId) - parseFloat(b.questionId)); 
      setAnswers(ans)
      console.log(answers)
  })

useEffect(()=>{
  console.log("useEffect")
  setFields(fieldsL.data)
},[])
let Questions = fieldsL.data.question;
let displayFields = Questions.map((e,index)=>{
return <div key={index} >
<label className="label">{e.content}</label>

<div className="control">
{
e.radio?  e.option.map((x,index2) => {

  console.log(index)
  //console.log(x)
 return <div classID="field" key={index2}>
<div classID="control">
  <label classID="checkbox">
    <label> {Object.keys(x)[0]}     </label>

    <input type="checkbox" name="question" onChange={()=> updateAnswer(e.questionId,Object.keys(x)[0],Object.values(x)[0])}/>
    &nbsp; {Object.values(x)[0]}
    { 

    }
  </label>
</div>
</div> }
) : <span>Empty</span>
}
</div>
</div>;
})

4
  • I guess you want to add the checked prop to your input component. Probably something like checked={answers[index].userChoice.option === Object.keys(x)}. Commented Sep 24, 2021 at 8:47
  • @Chris How would I get the index right there. Commented Sep 24, 2021 at 8:57
  • Oh, I see. You need to first find the correct answer in the array? Commented Sep 24, 2021 at 9:02
  • Exactly, Since the Array is Dynamic, There is a chance that there is no value for it. in which case it will remain unchecked, same if the "option" doesn't match. Commented Sep 24, 2021 at 9:03

1 Answer 1

1

In each iteration of your loop, you could do:

const value = Object.keys(x);
const answerIndex = answers.findIndex(a => a.userChoice.option === value);

and then in your return:

<input
  type="checkbox"
  name="question"
  checked={answerIndex >= 0}
  onChange={()=> updateAnswer(e.questionId,Object.keys(x)[0],Object.values(x)[0])}
/>

Obviously it would be better if your data was structured differently, as the above would give you an O(2n) complexity, since you'd be doing a loop inside a loop. However, for a smaller array, this shouldn't be an issue at all.

Sign up to request clarification or add additional context in comments.

4 Comments

I tried that before & now, the index returns -1 for each iteration. prnt.sc/1tfxnvg
@FaqahatFareed perhaps I've misunderstood how your data is modeled. If the key of x is meant to match a userChoice.option then this should work.
The Correct key would be Object.keys(x)[0] however it also doesn't seem to work, Can you suggest a better implementation for this?
Can you update your question with console.log outputs of answers (the whole structure) and Object.keys(x)?

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.