Home > Net >  How to select only one radio button for each object array in Flutter
How to select only one radio button for each object array in Flutter

Time:09-28

How to choose only one radio button for each question. now, in my code there is a problem when choosing the answer "option A" in the first question, then the answer "option X" in the second question is also selected. I don't want that to happen, I want when only selecting the answer from the first question, then only the radio button in the first question is selected. this is my data dummy:

  List<dynamic> dataDummy = [
  {
    "id": 1,
    "question": "Lorem ipsum dolor sit amet",
    "option": [
      {"id": 1, "name": "Option A"},
      {"id": 2, "name": "Option B"},
    ],
  },
  {
    "id": 2,
    "question": "consectetur adipiscing elit",
    "option": [
      {"id": 1, "name": "Option X"},
      {"id": 2, "name": "Option Y"},
    ],
  },
];

this is my code:

    int selectedRadio = 0;

  setSelectedRadio(int val) {
    setState(() {
      selectedRadio = val;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        shrinkWrap: true,
        padding: const EdgeInsets.all(8),
        itemCount: dataDummy.length,
        itemBuilder: (BuildContext context, int index) {
          var number = index   1;
          final optionAnswer = dataDummy[index]["option"];
          return Container(
            padding: EdgeInsets.all(10),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(height: 20),
                SizedBox(
                  width: MediaQuery.of(context).size.width * 0.9,
                  child: Text(
                    dataDummy[index]["question"],
                    maxLines: 5,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
                SizedBox(height: 10),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: optionAnswer.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      margin: EdgeInsets.only(bottom: 10),
                      child: ListTile(
                        title: Text(optionAnswer[index]["name"]),
                        trailing: Radio<dynamic>(
                          value: optionAnswer[index]["id"],
                          groupValue: selectedRadio,
                          onChanged: (val) {
                            setSelectedRadio(val);
                          },
                        ),
                      ),
                    );
                  },
                )
              ],
            ),
          );
        },
      ),
    );
  }

this is the result code:

enter image description here

CodePudding user response:

Use a map to store selected answer.

 Map<String, int> selectedAnswer = {};

And changes will be

trailing: Radio<int?>(
  value: optionAnswer[index]["id"],
  groupValue: selectedAnswer[question],
  onChanged: (val) {
    selectedAnswer[question] = val ?? -1;  //it wont trigger mostly, feels better than using !
    setState(() {});
  },
),

Test snippet

class RDTest extends StatefulWidget {
  const RDTest({super.key});

  @override
  State<RDTest> createState() => _RDTestState();
}

class _RDTestState extends State<RDTest> {
  List<dynamic> dataDummy = [
    {
      "id": 1,
      "question": "Lorem ipsum dolor sit amet",
      "option": [
        {"id": 1, "name": "Option A"},
        {"id": 2, "name": "Option B"},
      ],
    },
    {
      "id": 2,
      "question": "consectetur adipiscing elit",
      "option": [
        {"id": 1, "name": "Option X"},
        {"id": 2, "name": "Option Y"},
      ],
    },
  ];

  Map<String, int> selectedAnswer = {};

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        shrinkWrap: true,
        padding: const EdgeInsets.all(8),
        itemCount: dataDummy.length,
        itemBuilder: (BuildContext context, int index) {
          final List optionAnswer = dataDummy[index]["option"];
          final question = dataDummy[index]["question"];
          return Container(
            padding: EdgeInsets.all(10),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(height: 20),
                SizedBox(
                  width: MediaQuery.of(context).size.width * 0.9,
                  child: Text(
                    question,
                    maxLines: 5,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
                SizedBox(height: 10),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: optionAnswer.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      margin: EdgeInsets.only(bottom: 10),
                      child: ListTile(
                        title: Text(optionAnswer[index]["name"]),
                        trailing: Radio<int?>(
                          value: optionAnswer[index]["id"],
                          groupValue: selectedAnswer[question],
                          onChanged: (val) {
                            selectedAnswer[question] =
                                val ?? 0; //it wont trigger mostly
                            setState(() {});
                          },
                        ),
                      ),
                    );
                  },
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

CodePudding user response:

Because you have the same id in both of your questions.

You have to change the ids or use this optionAnswer[index]["name"] instead of optionAnswer[index]["id"]

CodePudding user response:

value parameter on the radio is what makes it unique, in your case you have same values because optionAnswer[index]["id"] are equal, consider alway making id something unique f.e. use UniqueKey()

  • Related