2

Right now only one selection is allowed between all inputs. I'm not sure how to solve this. I thought the name was supposed to match between all inputs, but perhaps I'm wrong. If I remove it, then there is an endless number of input selections allowed.

How can I fix this? Thank you.

{props.Data.map((item, index) => {
            return (
                <div key={index}>
                    <h3>{item.question}</h3>
                
                    <input
                        type="radio"
                        name="answer option"
                        id={`answer-options-${index}`}
                        value={results}
                        onChange={e => setResults(e.target.value)}/>
                            <label htmlFor={`answer-options-${index}`}>
                                {item.answers[0]}
                            </label>    
                    <input
                        type="radio"
                        name="answer option"
                        id={`answer-options-${index}`}
                        value={results.selectedAnswer}
                        onChange={handleSelectedAnswer}/>
                            <label htmlFor={`answer-options-${index}`}>
                                {item.answers[1]}
                            </label>  
                    <input
                        type="radio"
                        name="answer option"
                        id={`answer-options-${index}`}
                        value={results.selectedAnswer}
                        onChange={handleSelectedAnswer}/>
                            <label htmlFor={`answer-options-${index}`}>
                                {item.answers[2]}
                            </label>
                    <input
                        type="radio"
                        name="answer option"
                        id={`answer-options-${index}`}
                        value={results.selectedAnswer}
                        onChange={handleSelectedAnswer}/>
                            <label htmlFor={`answer-options-${index}`}>
                                {item.answers[3]}
                            </label>
                   
                </div>
            )
        })}   
        <button
            onClick={() => {
                    checkSelectedAnswer();
                    scoreQuiz();
                    finishQuiz()}
                }>
            Check answers
        </button>
agm
  • 91
  • 1
  • 6
  • 2
    What are you trying to fix? You want only one selectable at-a-time like your title suggests and you say you are doing and your code matches, or you want to remove the `name` attribute so you can select multiple? – Drew Reese Feb 03 '22 at 06:46
  • @DrewReese There are 4 displayed answers each with 4 options because I'm mapping over an array (just updated my code to show this). Right now if I click one selection (or answer) in a set, I can't hold it selected when I click input from a different set. Like a regular multiple choice quiz it should allow me to select one per input and hold it regardless of the other selections. ie how old are you? 10, 20, 30 (30 selected and held), are you male or female? male, female (male selected and held)... – agm Feb 03 '22 at 07:13

1 Answers1

1

It appears you are giving all radio input the same name attribute when in reality you are mapping "sets", or groups, of radio inputs. You want each "set"/group to have a unique name attribute, similarly to what was done for the id attributes.

{props.Data.map((item, index) => {
  return (
    <div key={index}>
      <h3>{item.question}</h3>

      <input
        type="radio"
        name={`answer option-${item.question}`}
        id={`answer-options-${index}`}
        value={results}
        onChange={(e) => setResults(e.target.value)}
      />
      <label htmlFor={`answer-options-${index}`}>{item.answers[0]}</label>
      <input
        type="radio"
        name={`answer option-${item.question}`}
        id={`answer-options-${index}`}
        value={results.selectedAnswer}
        onChange={handleSelectedAnswer}
      />
      <label htmlFor={`answer-options-${index}`}>{item.answers[1]}</label>
      <input
        type="radio"
        name={`answer option-${item.question}`}
        id={`answer-options-${index}`}
        value={results.selectedAnswer}
        onChange={handleSelectedAnswer}
      />
      <label htmlFor={`answer-options-${index}`}>{item.answers[2]}</label>
      <input
        type="radio"
        name={`answer option-${item.question}`}
        id={`answer-options-${index}`}
        value={results.selectedAnswer}
        onChange={handleSelectedAnswer}
      />
      <label htmlFor={`answer-options-${index}`}>{item.answers[3]}</label>
    </div>
  );
})}

A DRY version mapping the array of answers:

{props.Data.map((item, index) => {
  return (
    <div key={index}>
      <h3>{item.question}</h3>
      {item.answers.map((answer) => (
        <React.Fragment key={answer}>
          <input
            type="radio"
            name={`answer option-${item.question}`}
            id={`answer-options-${index}`}
            value={results}
            onChange={(e) => setResults(e.target.value)}
          />
          <label htmlFor={`answer-options-${index}`}>{answers}</label>
        </React.Fragment>
      ))}
    </div>
  );
})}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    Thank you! The first code worked, but unfortunately, the latter did not. – agm Feb 04 '22 at 05:11
  • @agm I see, the second should be pretty close to working, but without seeing it working with more of your code it's not clear what minor tweak is likely needed. Otherwise, welcome, glad to help out. Cheers and good luck! – Drew Reese Feb 04 '22 at 17:55
  • Thank you again! What's typically the best way to share more code as in other components etc? Just curious for future questions. Would a URL work? I'm learning on Scrimba and they offer URL access. – agm Feb 06 '22 at 03:45
  • @agm Either in your question if it's relevant, otherwise in a running codesandbox with a link in a comment is good. – Drew Reese Feb 07 '22 at 22:25