'Make child elements active
I have a code that can be used to filter cars by country of manufacture. The code is structured like this: I put the name of the country with a checkbox in the title ExpansionTile; I put the name of the cars with checkboxes in the children ExpansionTile. Those. the user can tick either only the country, or only the names (name) of the car, or all together.
But I would like to implement the idea that if the user puts a checkmark next to the name of the country, then the checkboxes in front of the cars would be automatically checked. Similar to the functionality from this example https://medium.com/@nishsvn.dev/flutter-parent-and-child-checkboxes-part-2-98ce62156004
    class _FilterDialogUserState extends State<FilterDialogUser> {
  Map<String, List<String>?> filters = {};
  @override
  void initState() {
    super.initState();
    filters = widget.initialState;
  }
  void _handleCheckFilter(bool checked, String key, String value) {
    final currentFilters = filters[key] ?? [];
    if (checked) {
      currentFilters.add(value);
    } else {
      currentFilters.remove(value);
    }
    setState(() {
      filters[key] = currentFilters;
    });
  }
  final countries = [
    Country(
      name: 'Germany',
      cars: [
        Car(name: 'Audi'),
        Car(name: 'BMW'),
        Car(name: 'Volkswagen'),
      ],
    ),
    Country(
      name: 'Sweden',
      cars: [
        Car(name: 'Koenigsegg'),
        Car(name: 'Polestar'),
        Car(name: 'Volvo'),
      ],
    ),
    Country(
      name: 'Russian',
      cars: [
        Car(name: 'GAZ'),
        Car(name: 'Lada'),
        Car(name: 'ZAZ'),
      ],
    ),
  ];
  @override
  Widget build(BuildContext context) {
    return SimpleDialog(
        title: const Text('Filters',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontSize: 25,
              fontFamily: 'SuisseIntl',
            )),
        contentPadding: const EdgeInsets.all(16),
        children: [
          Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                for (Country country in countries)
                  ExpansionTile(
                      tilePadding: EdgeInsets.zero,
                      childrenPadding: const EdgeInsets.symmetric(horizontal: 15),
                      title: CustomCheckboxTile(
                        value:
                        filters['country']?.contains(country.name) ?? false,
                        onChange: (check) =>
                            _handleCheckFilter(check, 'country', country.name),
                        label: country.name,
                      ),
                      initiallyExpanded: () {
                        for (final Car car in country.cars) {
                          if (filters['cars']?.contains(car.name) ?? false) {
                            return true;
                          }
                        }
                        return false;
                      }(),
                      children: [
                        for (Car car in country.cars)
                          CustomCheckboxTile(
                            value: filters['cars']?.contains(car.name) ?? false,
                            onChange: (check) =>
                                _handleCheckFilter(check, 'cars', car.name),
                            label: car.name,
                          )
                      ])
              ]),
       ........
If you need additional pieces of code to help solve the problem, let me know.
Solution 1:[1]
You need to connect the relation between the Checkbox of Country and the Checkbox of Car. The most straightforward method to do in your code is updating the function of _handleCheckFilter. It needs some more additional information to update the filter.
I split it into 2 functions: _handleCountryCheckFilter and _handleCarCheckFilter:
_handleCountryCheckFilter
void _handleCountryCheckFilter(
    bool checked, String country, List<String> cars) {
  final countryFilters = filters['country'] ?? [];
  final carFilters = filters['cars'] ?? [];
  if (checked) {
    countryFilters.add(country);
    for (var car in cars) {
      if (!carFilters.contains(car)) {
        carFilters.add(car);
      }
    }
  } else {
    countryFilters.remove(country);
    for (var car in cars) {
      if (carFilters.contains(car)) {
        carFilters.remove(car);
      }
    }
  }
  setState(() {
    filters['country'] = countryFilters;
    filters['cars'] = carFilters;
  });
}
_handleCarCheckFilter
void _handleCarCheckFilter(
    bool checked, String car, String country, List<String> cars) {
  final countryFilters = filters['country'] ?? [];
  final carFilters = filters['cars'] ?? [];
  if (checked) {
    carFilters.add(car);
    var carIsFull = true;
    for (var car in cars) {
      if (!carFilters.contains(car)) {
        carIsFull = false;
      }
    }
    if (carIsFull && !countryFilters.contains(country)) {
      countryFilters.add(country);
    }
  } else {
    carFilters.remove(car);
    var carIsEmpty = true;
    for (var car in cars) {
      if (carFilters.contains(car)) {
        carIsEmpty = false;
      }
    }
    if (carIsEmpty) {
      countryFilters.remove(country);
    }
  }
  setState(() {
    filters['country'] = countryFilters;
    filters['cars'] = carFilters;
  });
}
Finally, you can change the onChange function of your CustomCheckboxTile:
// country checkbox
CustomCheckboxTile(
  value: filters['country']?.contains(country.name) ?? false,
  onChange: (check) => _handleCountryCheckFilter(check,country.name,country.cars.map((car) => car.name).toList()),
  label: country.name,
),
...
// country checkbox
CustomCheckboxTile(
  value: filters['cars']?.contains(car.name) ?? false,
  onChange: (check) => _handleCarCheckFilter(check,car.name,country.name,country.cars.map((car) => car.name).toList()),
  label: car.name,
)
    					Solution 2:[2]
Try this I Hope it works for you.
          @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  for (Country country in countries)
                    ExpansionTile(
                        tilePadding: EdgeInsets.zero,
                        childrenPadding: const EdgeInsets.symmetric(horizontal: 15),
                        title: CheckboxListTile(
                          value:
                          getCountryValue(country),
    
                          onChanged: (check) =>
                              onCountrySelected(check!, country),
                          title: Text(country.name!),
                        ),
                        initiallyExpanded: () {
                          return false;
                        }(),
                        children: [
                          for (Car car in country.cars!)
                            CheckboxListTile(
                              value: selectedCar.contains(car),
                              onChanged: (check) =>
                                  _handleCheckFilter(check!, 'cars', car),
                              title: Text(car.name!),
                            )
                        ])
                ]),
          ),
        );
      }
    
    
    
      List<Car> selectedCar = [];
    
      void _handleCheckFilter(bool checked, String key, Car car) {
        if (checked) {
        selectedCar.add(car);
        } else {
          selectedCar.remove(car);
        }
        setState(() {
        });
      }
    
      onCountrySelected(bool checked, Country country) {
        if (checked) {
          country.cars!.forEach((element) {
            if (!selectedCar.contains(element)) {
              selectedCar.add(element);
            }
          });
        } else {
          country.cars!.forEach((element) {
            selectedCar.remove(element);
          });
        }
        setState(() {
    
        });
      }
    
      bool getCountryValue(Country country) {
        bool selected = country.cars!.where((element) => selectedCar.contains(element)).length == country.cars!.length;
        return selected;
      }
    
      List<Country> countries = [
        Country(
          name: 'Germany',
          cars: [
            Car(name: 'Audi'),
            Car(name: 'BMW'),
            Car(name: 'Volkswagen'),
          ],
        ),
        Country(
          name: 'Sweden',
          cars: [
            Car(name: 'Koenigsegg'),
            Car(name: 'Polestar'),
            Car(name: 'Volvo'),
          ],
        ),
        Country(
          name: 'Russian',
          cars: [
            Car(name: 'GAZ'),
            Car(name: 'Lada'),
            Car(name: 'ZAZ'),
          ],
        ),
      ];
    }
    					Solution 3:[3]
Try this. It will keep the states
class _FilterDialogUserState extends State<FilterDialogUser> with AutomaticKeepAliveClientMixin {
   @override
   bool get wantKeepAlive => true;
   
   @override
   Widget build(BuildContext context) {
     super.build(context);
   }
}
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | yellowgray | 
| Solution 2 | Kishan Busa | 
| Solution 3 | Minjin Gelegdorj | 
