'How to pass objects based on key from one stateful widget to another stateful widget

I have this json objects where i specify the menu objects and view objects.

# test.json

{
  "data": {
    "user" : "user1",
    "menu": [
      {
        "label": "Books",
        "view": "books"
      },
      {
        "label": "Author",
        "view": "authors"
      },
      {
        "label": "Publishers",
        "view": "publishers"
      }

    ],
    "view": {
      "books": [
        {
          "block_type": "title",
          "block_data": "Books"
        },
        {
          "block_type": "text",
          "block_data": "This is the view for Books"
        }
      ],
      "authors": [
        {
          "block_type": "title",
          "block_data": "Author"
        },
        {
          "block_type": "text",
          "block_data": "This is the view for Author"
        }
      ],
      "publishers": [
        {
          "block_type": "title",
          "block_data": "Publishers"
        },
        {
          "block_type": "text",
          "block_data": "This is the for Publishers"
        }
      ]
    }
  }
}

I use class called AppContent() with the method getAppContent() to grab the json. I use the menu objects to display the labels inside a drawer menu:

class AppMenu extends StatefulWidget {
  const AppMenu({Key? key}) : super(key: key);

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

class _AppMenuState extends State<AppMenu> {
  late Map<String, dynamic> testObject = {};

  setTestData() async {
    await AppContent()
        .getAppContent()
        .then((result) => setState(() => testObject = result));
  }

  @override
  initState() {
    setTestData();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
        child: ListView(padding: EdgeInsets.zero, children: [
      DrawerHeader(child: Container()),
      Column(
        children: [
          ListView.builder(
              physics: const NeverScrollableScrollPhysics(),
              shrinkWrap: true,
              itemCount: testObject.containsKey("data")
                  ? (testObject["data"]["menu"] as List<dynamic>).length
                  : 0,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  onTap: () {
                    Navigator.pushAndRemoveUntil(
                      context,
                      MaterialPageRoute(
                        builder: (BuildContext context) => AppView(),
                      ),
                      (route) => false,
                    );
                  },
                  title: Center(
                    child: Column(
                      children: [
                        Text(
                          (testObject["data"]["menu"] as List<dynamic>)[index]
                              ["label"],
                        ),
                      ],
                    ),
                  ),
                );
              }),
        ],
      ),
    ]));
  }
}

Image below views the list of items i show from the json object:

enter image description here

I also have a stateful widget in a seperate file called AppView where i want to show the view objects based on the label that is clicked from the menu.


class AppView extends StatefulWidget {
  const AppView({Key? key}) : super(key: key);

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

class _AppViewState extends State<AppView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      drawer: AppMenu(),
      body: Center(child: Text("AppView")),
    );
  }
}

The AppView is empty because i don't know how to show the view objects from the json object. For example if you click on Books i want to show the objects inside the key ["view"]["books"]. I wonder how i can this?



Solution 1:[1]

Good day,

You will need to pass the items corresponding to your selected menu to your AppView. To do so edit your MaterialPageRoute in your _AppMenuState as follows.

...

MaterialPageRoute(
       builder: (BuildContext context) => AppView(selectedMenuItems:  testObject["data"]["view"][testObject["data"]["menu"] as List<dynamic>[index]["view"]]),
    ),

...

Secondly, you will then have to make your AppView accept the parameter (selectedMenuItems) as below.

 class AppView extends StatefulWidget {
  final List selectedMenuItems;

  AppView({Key key, @required this.selectedMenuItems})
      : super(key: key);
  @override
  _AppViewState createState() => _AppViewState();
}

class _AppViewState extends State<AppView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      drawer: AppMenu(),
      body: //Iterate through the selectedMenuItems List
    );
  }
}

That being said, I would recommend you revisit the way you are iterating your testObject inside the ListViewBuilder.

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 keptac