Handle the list of dynamic checkboxes when the widget is added on button click in flutter

669

This issue is because you control all replica by counting and widget.responseMarket. If you want all replicas work individually, you need to Replica it actually.

I suggest to create a new StatefulWidget to replace _buildSingleCheckBox() & _buildCheckBoxes() function. I also put showHidee inside it.

class CheckBoxesWidget extends StatefulWidget {
  final responseMarket;

  CheckBoxesWidget({this.responseMarket, Key key}) : super(key: key);

  @override
  _CheckBoxesWidgetState createState() => _CheckBoxesWidgetState();
}

class _CheckBoxesWidgetState extends State<CheckBoxesWidget> {
  bool showHidee;

  @override
  void initState() {
    showHidee = true;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          InkWell(
            onTap: () {
              showHide();
            },
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text(
                  'productionmareketway',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                showHidee
                    ? Icon(Icons.keyboard_arrow_up)
                    : Icon(Icons.keyboard_arrow_down)
              ],
            ),
          ),
          SizedBox(
            width: 20,
          ),
          if (showHidee)
            Column(
              children: widget.responseMarket
                  .map(
                    (e) => CheckboxListTile(
                      title: Text(e.name),
                      value: e.isChecked,
                      activeColor: Theme.of(context).primaryColor,
                      checkColor: Colors.white,
                      onChanged: (bool value) {
                        setState(() {
                          e.isChecked = value;
                        });
                      },
                    ),
                  )
                  .toList(),
            ),
        ],
      ),
    );
  }

  void showHide() {
    setState(() {
      showHidee = !showHidee;
    });
  }
}

Second, beyond control the replica by counting, you should use a List to store all replica of responseMarket in the original class.

List<List<Market>> responseMarkets;

@override
void initState() {
  responseMarkets = [widget.responseMarket];
  super.initState();
}

...
@override
Widget build(BuildContext context) {
  return ListView.builder(
      itemCount: responseMarkets.length,
      itemBuilder: (_, index) {
        return _buildLayout(context, index);
      });
}

...
Widget _buildLayout(BuildContext context, int i) {
  ...
  // replace _buildCheckBoxes() with this line
  CheckBoxesWidget(responseMarket: responseMarkets[i],), 
  ...
}

Finally, you have to modify the addRow, deleteRow function. Each time create a new ResponseMarkets Object.

addRow(int i) {
  setState(() {
    responseMarkets.add(responseMarkets[0]
        .map((e) => ResponseMarkets(
              id: e.id,
              name: e.name,
              identifier: e.identifier,
              isChecked: e.isChecked,
            ))
        .toList());
  });
}

deleteRow(int i) {
  setState(() {
    responseMarkets.removeAt(i);
  });
}
Share:
669
Nabin Dhakal
Author by

Nabin Dhakal

Updated on December 13, 2022

Comments

  • Nabin Dhakal
    Nabin Dhakal over 1 year

    When clicking the add button, the same widget is replicated. The widget contains the list of checkboxes that are multi selectable. I am able to replicate the widget but I got problem to handle the checkboxes according to the index of the widget. In image below the checkbox checked state is replicated along with the new add widget.

    enter image description here

    I have implemented as follows:

    Build the widget according to the addbutton click

      ListView.builder(
                      itemCount: counting,
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      itemBuilder: (_, index) {
                        return _buildLayout(context, index);
                      });
    
    
    
                     //counting is number of **blueplus** icon is clicked
         Widget  _buildLayout(BuildContext context, int i) {       
          return Column(
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text(
                  addContainer,
                  style: TextStyle(color: Colors.blueGrey),
                ),
                Container(
                  width: 64.0,
                  alignment: Alignment.center,
                  child: IconButton(
                      onPressed: () => {i == 0 ? addRow(i) : deleteRow(i)},
                      icon: Icon(
                        i == 0
                            ? Icons.add_circle_outline
                            : Icons.remove_circle_outline,
                        color: i == 0 ? Theme.of(context).primaryColor : Colors.red,
                      )),
                ),
              ],
            ),        
            _buildCheckBoxes()
          ],
        );
      }
    
    
    
    Widget _buildCheckBoxes() {
        return
            Container(         
                width: MediaQuery.of(context).size.width,
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      InkWell(
                          onTap: () {
                            showHide();
                          },
                          child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: <Widget>[
                                Text(
                                  productionmareketway,
                                  style: TextStyle(
                                      fontSize: 18, fontWeight: FontWeight.bold),
                                ),
                                showHidee
                                    ? Icon(Icons.keyboard_arrow_up)
                                    : Icon(Icons.keyboard_arrow_down)
                              ])),
                      SizedBox(
                        width: 20,
                      ),
                      showHidee
                          ? ListView.builder(
                              shrinkWrap: true,
                              physics: const NeverScrollableScrollPhysics(),
                              itemCount: widget.responseMarket.length,
                              itemBuilder: (ctx, i) {
                                return _buildSingleCheckBox(
                                    context,
                                    widget.responseMarket[i].name,
                                    widget.responseMarket[i].isChecked,
                                    widget.responseMarket[i].id,
                                    widget.responseMarket[i].identifier,
                                    i);
                              })
                          : Container()
                    ])
               );
              } 
      
    
    
    
    Widget _buildSingleCheckBox(BuildContext context, String name, bool isChecked,
          int i, String identifier, int j) {
        return Container(
          child: new CheckboxListTile(
            title: new Text(name),
            value: isChecked,
            activeColor: Theme.of(context).primaryColor,
            checkColor: Colors.white,
            onChanged: (bool value) {
              setState(() {
                widget.responseMarket[i].isChecked = value;
                print(value);
                print(i);
    
                widget._onChecked(
                    value,
                    widget.responseMarket[i].id,
                    widget.responseMarket[i].name,
                    widget.responseMarket[i].identifier,
                    counting);
              });
            
            },
          ),
        );
      }
    

    Add and delete widget function

    addRow(int i) {
    setState(() {
      counting = counting + 1;
    });
    } 
    
     deleteRow(int i) {
        setState(() {
          counting = counting - 1;
        });
      }
    

    My callback function

     onMarketChecked(var value, int i, String name, String identifier, int j) {
    setState(() {
      if (responseMarket[i].isChecked == true) {
        nonMarketRepated.add(name);
      } else {
        nonMarketRepated.remove(responseMarket[i].name);
      }
    });
    }
    
  • Nabin Dhakal
    Nabin Dhakal over 3 years
    It worked in case when no checkbox items is selected of the container index 0 and the container is added, but when selecting the checkboxlist items layout of container index 0 and adding containers the new container added will have the values as like in index 0 container.
  • yellowgray
    yellowgray over 3 years
    I notice I didn't fix your issue becaue the original replica is control by counting and widget.responseMarket (which is final from this object created). I modify it and update the code.