On Flutter go_router how to change only content of special container?

121 Views Asked by At

I have a page in Flutter which has 3 different elements header, sidebar and main_content. Sidebar contains some text buttons login, customer, manager etc.

When someone clicks on the button on the sidebar i want to change only the content of the main_content. I dont want to replace whole screen. I just want to replace the content of main_content with another widget.

I am not sure if it can be done using flutter package go_router. Or I have to use state management for this case.

I tried Go_router shell routes. But i think it is made for different purpose.

enter image description here

4

There are 4 best solutions below

1
Reza Khajvand On BEST ANSWER

router config :

final GlobalKey<NavigatorState> _shellNavigatorKey =
GlobalKey<NavigatorState>(debugLabel: 'shell');

const String pageOne = '/pageone';
const String pageTwo = '/pagetwo';

final appRouter = GoRouter(
  initialLocation: pageOne,
  routes: [
    ShellRoute(
      navigatorKey: _shellNavigatorKey,
      builder: (BuildContext context, GoRouterState state, Widget child) {
        return MainPage(child: child);
      },
      routes: [
        GoRoute(
          path: pageOne,
          builder: (BuildContext context, GoRouterState state) =>
              const MainContent(lable: 'one'),
        ),
        GoRoute(
          path: pageTwo,
          builder: (BuildContext context, GoRouterState state) =>
              const MainContent(lable: 'two'),
        ),
      ],
    )
  ],
);

main page class :

class MainPage extends StatelessWidget {
  //child is the content of each page
  final Widget child;
  const MainPage({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          //SideBar
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.blue,
              child: ListView(
                children: [
                  GestureDetector(
                      onTap: () => context.go(pageOne),
                      child: const Text('page One')),
                  GestureDetector(
                      onTap: () => context.go(pageTwo),
                      child: const Text('page Two')),
                ],
              ),
            ),
          ),
          Expanded(
              flex: 2,
              child: Column(
                children: [
                  //Header
                  Container(
                    width: double.infinity,
                    padding: const EdgeInsets.all(16),
                    color: Colors.red,
                    child: const Text('Header'),
                  ),
                  //main_MainContent
                  Expanded(child: child),
                ],
              )),
        ],
      ),
    );
  }
}

main content class :

    class MainContent extends StatelessWidget {
  final String lable;
  const MainContent({super.key, required this.lable});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(lable),
      ),
    );
  }
}

run app :

    void main(List<String> args) {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: appRouter,
    );
  }
}

resault :

enter image description here

1
Vivek Chib On

This can be achieved with shellRoutes in go_router. But if you just want to change the content of the page, then you can follow this approach:

class TestPage extends StatefulWidget {
  const TestPage({super.key});

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  int _selection = 0;

  List<Widget> content = [
    Container(height: double.infinity, color: Colors.grey),
    Container(height: double.infinity, color: Colors.green),
    Container(height: double.infinity, color: Colors.orange),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      drawer: Drawer(
        child: ListView.builder(
          itemCount: content.length,
          itemBuilder: (context, index) {
            return ListTile(
              onTap: () {
                setState(() {
                  _selection = index;
                });
              },
              title: Text("Option ${index + 1}"),
            );
          },
        ),
      ),
      body: content[_selection],
    );
  }
}

demo

0
WebDesk Solution On

Following my suggestion, you would initialize a variable named _currentMainContent with a type of Widget, setting it initially to a Placeholder widget. This variable would represent the main content area of your application.

Whenever a user interacts with a side menu item, you would update the _currentMainContent variable to display the appropriate widget corresponding to the selected menu item. This approach allows for dynamic content switching within the main content area of your application.

3
Reza Khajvand On

the purpose of using shellroute is for solving youre problem use it in youre project enter image description here

enter image description here

just like my example here i just change the content when switching between sidebar item