Search code examples
flutterradio-buttonradiobuttonlist

Flutter OnChanged behaviour in Radios with multiple groups not working as expected


Hi The problem is I have multiple groups of RadioButtons hence can't figure out how onChanged method will work for each group. I have a list of students and want to make a widget where a teacher can mark attendance of students by clicking on one of the Radio Buttons( present,absent,holiday,half day etc.) Here is the implementation

@override
Widget build(BuildContext context) {
print('number students ${studentList.students.length.toString}');
return ListView.builder(
    itemCount: studentList.students.length,
    itemBuilder: (context, index) {
      var gp = studentList.students[index].id;
      return Padding(
        padding: const EdgeInsets.all(8.0),
        child: Card(
          elevation: 10,
          child: ListTile(
            title: Padding(
              padding: const EdgeInsets.only(top: 8.0),
              child: Text(
                studentList.students[index].name,
                style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
              ),
            ),
            leading: CircleAvatar(
                radius: 30,
                backgroundImage: NetworkImage(
                    studentList.students[index].details['photo'])),
            trailing: Column(
              children: <Widget>[],
            ),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text('Phone: ' +
                    studentList.students[index].details['phone']),
                Text('Batches:'),
                Container(
                  width: MediaQuery.of(context).size.width,
                  height: 50,
                  child: ListView.builder(
                    itemCount: studentList.students[index].batches.length,
                    itemBuilder: (context, batchIndex) {
                      return Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(studentList
                              .students[index].batches[batchIndex].name),
                        ],
                      );
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: <Widget>[
                      Column(
                        children: <Widget>[
                          Radio(
                            groupValue: gp,
                            value: 0,
                            onChanged: (int e) {
                              print(e);
                              print(gp);
                              updateSelectedAttendance(gp, e);

                            },
                          ),
                          Text('P')
                        ],
                      ),
                      Column(
                        children: <Widget>[
                          Radio(
                            groupValue: gp,
                            onChanged: (int e) {
                              print(e);
                              print(gp);
                              updateSelectedAttendance(gp, e);

                            },
                            value: 1,
                          ),
                          Text('Ab')
                        ],
                      ),
                      Column(
                        children: <Widget>[
                          Radio(
                            groupValue: gp,
                            onChanged: (int e) {
                              print(e);
                              print(gp);
                              updateSelectedAttendance(gp, e);

                            },
                            value: 2,
                          ),
                          Text('Hd')
                        ],
                      ),
                      Column(
                        children: <Widget>[
                          Radio(
                            groupValue: gp,
                            onChanged: (int e) {
                              print(e);
                              print(gp);
                              updateSelectedAttendance(gp, e);

                            },
                            value: 3,
                          ),
                          Text('H')
                        ],
                      )
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      );
    });

}

 updateSelectedAttendance(int gp, int e) {
setState(() {
  gp = e;
  print('gp ${gp.toString()} -- e ${e.toString()}');
});

}

enter image description here

Here because there would be multiple students , hence there would be multiple groups of Radio Buttons so I have assigned each group a groupValue of id of the individual student. And because there are 4 radio buttons for each student (present,absent,holiday,halfday), I have assigned values of 0,1,2,3. And in onChanged method I am equating gp=value; But it is not behaving the way I want it to behave.


Solution

  • //For the deom purpose I'm using Map List...
      //Replace the above with your custom model
      List<Map> studentList=[];
      //Create attendance list to hold attendance
      Map<String,String> attendance={};
    
      List<String> labels=['P','Ab','Hd','H'];
    
      @override
      void initState() {
        super.initState();
        getData();
      }
    
      getData(){
        //Use your own implementation to get students data
        //For deom I'm using offline data
        studentList.add({
          'id':'ID1',
          'name':'Naveen Avidi',
          'details':'A Programmer'
            //other fields...
        });
        attendance['ID1']='P';
        //or null if emtpy
        studentList.add({
          'id':'ID2',
          'name':'Ram',
          'details':'An Engineer'
            //other fields...
        });
        attendance['ID2']='Ab';
        //or null if emtpy
        studentList.add({
          'id':'ID3',
          'name':'Satish',
          'details':'A Developer'
            //other fields...
        });
        attendance['ID3']='Hd';
        //or null if emtpy
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar:AppBar(
          title:Text('Title')),
          body: Container(
            color:Colors.white,
              child: ListView.builder(
        itemCount: studentList.length,
        itemBuilder: (context, index) {
          return Padding(
            padding: const EdgeInsets.all(8.0),
            child: Card(
              color:Colors.cyan,
              elevation: 10,
              child: ListTile(
                title: Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: Text(
                    studentList[index]['name'],
                    style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold,color:Colors.black),
                  ),
                ),
                leading: CircleAvatar(
                    radius: 30,
                  //no pic available 
                ),
                trailing: Column(
                  children: <Widget>[],
                ),
                subtitle: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('Phone: ' +
                        studentList[index]['details'],
                        style:TextStyle(color:Colors.black)),
                    Text('Batches:',style:TextStyle(color:Colors.black)),
    //                 Container(
    //                   width: MediaQuery.of(context).size.width,
    //                   height: 50,
    //                   child: ListView.builder(
    //                     itemCount: studentList.students[index].batches.length,
    //                     itemBuilder: (context, batchIndex) {
    //                       return Column(
    //                         crossAxisAlignment: CrossAxisAlignment.start,
    //                         children: <Widget>[
    //                           Text(studentList
    //                               .students[index].batches[batchIndex].name),
    //                         ],
    //                       );
    //                     },
    //                   ),
    //                 ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: labels.map((s){
                          return Column(
                            children: <Widget>[
                              Radio(
                                groupValue: attendance[studentList[index]['id']],
                                value: s,
                                onChanged: (newValue) {
                                  setState((){
                                    attendance[studentList[index]['id']]=newValue;
                                  });
                                },
                              ),
                              Text(s,style:TextStyle(color:Colors.black))
                            ],
                          );
                        }).toList(),
                      ),
                    )
                  ],
                ),
              ),
            ),
          );
        })
          ),
        );
      }
    

    SS