Flutter: Loop through all children of a widget

Viewed 832

I need to loop over my widget screen/page and edit my current widget by server results: i am getting an list of objects like this:

{
  "states": [
    {
      "id": "1",
      "visible": true,
      "enable": false
    },
    {
      "id": "2",
      "visible": false,
      "enable": false
    }
  ]
}

Each id point of widget that contains KeyValue, i need to search for wholes keys in my page/screen that match to my server id's than edit current widget with it properties. i need to do it first time before build function called, so i created WidgetTree, that get screen widget as param(child) and loop over it in initState and recreate the new child(screen/page) with all the updates. then build will call the new child.

My code:

class WidgetTree extends StatefulWidget {

  final Widget child;

  const WidgetTree({Key? key,required this.child}) : super(key: key);

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

class _WidgetTreeState extends State<WidgetTree> {

  late Widget parent;

  @override
  void initState() {
    parent = widget.child;
    _widgetRecursion(null, parent);
    super.initState();
  }

  _widgetRecursion(Widget? parent,Widget? child){
    if(child == null) return;

    if(child is RegularButton){

      // child = Visibility(child: child,visible: false,); // not working i am losing refrence.
    }

    if(child is Scaffold){
      _widgetRecursion(child,child.body);
    }

    if(child is Container){
      _widgetRecursion(parent,child.child);
    }

    if(child is MultiChildRenderObjectWidget){
      child.children.forEach((subChild)=>_widgetRecursion(child,subChild));
    }

    if(child is SingleChildScrollView){
      _widgetRecursion(child,child.child);
    }
    if(child is SingleChildRenderObjectWidget){
      _widgetRecursion(child,child.child);
    }
    if(child is StreamBuilder){
      // final t = child as StatefulWidget;
    }
  }

  @override
  Widget build(BuildContext context) {
    return parent;
  }
}
1 Answers

I haven't seen any code that may modify the existing widget tree. I think it is better to add Visibility to every RegularButton (or other widgets you want to control) and then control them by searching the key. You can do it by controlling all keys somewhere (like provider, GlobalKey + StatefulWidget, or something else that can manage the widget statement) and change the widget state directly.

If you try to recursively track down and modify the tree, I can only think of copying a new one. That means you must replica all the widgets you tracked:

// original tree is widget.child
...
late Widget newTree;

@override
void initState() {
  newTree = _widgetRecursion(null, widget.child);
  super.initState();
}

Widget _widgetRecursion(Widget? parent,Widget? child) {
  if(child is RegularButton){
      return Visibility(child: child,visible: false,);
  }
  if(child is SomeWidget){
     return SomeWidget(
       someProperty: child.someProperty,
       child: _widgetRecursion(child, child.child),
     );
  }
  if(child is TopWidget){
    return TopWidget(child: _widgetRecursion(child, child.child);
  }
}

@override
Widget build(BuildContext context) {
  return newTree;
}
...
Related