Flutter nested routing

851

You can do something like that using this package qlevar_router

A full example of your case

import 'package:flutter/material.dart';
import 'package:qlevar_router/qlevar_router.dart';

void main() {
  runApp(MyApp());
}

class AppRoutes {
  final routes = <QRouteBase>[
    QRoute(
      path: '/page-one',
      page: (c) => PageOne(),
    ),
    QRoute(
        path: '/page-two',
        page: (c) => PageTwo(c),
        initRoute: '/part-1',
        children: [
          QRoute(
            path: '/part-1',
            page: (c) => Part1(),
          ),
          QRoute(
            path: '/part-2',
            page: (c) => Part2(),
          )
        ])
  ];
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: QR.router(AppRoutes().routes, initRoute: '/page-one'),
      routeInformationParser: QR.routeParser(),
    );
  }
}

class PageOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(children: [
          Text('This is page one'),
          TextButton(
              onPressed: () => QR.to('/page-two/part-1'),
              child: Text('To Part 1')),
          TextButton(
              onPressed: () => QR.to('/page-two/part-2'),
              child: Text('To Part 2')),
        ]),
      ),
    );
  }
}

class PageTwo extends StatelessWidget {
  final QRouteChild child;
  PageTwo(this.child);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(children: [
          Text('This is page one'),
          TextButton(onPressed: () => QR.back(), child: Text('Back')),
          TextButton(
              onPressed: () => QR.to('/page-two/part-1'),
              child: Text('To Part 1')),
          TextButton(
              onPressed: () => QR.to('/page-two/part-2'),
              child: Text('To Part 2')),
          SizedBox(
            width: 500,
            height: 500,
            child: child.childRouter,
          )
        ]),
      ),
    );
  }
}

class Part1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('This is part 1'));
  }
}

class Part2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('This is part 2'));
  }
}

Note that page-tow doesn't change at all when you navigate between the children part-1 and part-2

Share:
851
Paul Kruger
Author by

Paul Kruger

Updated on December 11, 2022

Comments

  • Paul Kruger
    Paul Kruger over 1 year

    I am very new to Flutter but coming from an Angular background here. Say I want to build a BaseFrame for my app, and depending on the routing, I want to change the INSIDE of that BaseFrame. I don't understand how this would work?

    In Angular it would be something like:

    '/page-one': PageOne(),
    '/page-two': PageTwo(), children: [
        '/part-1': Part1(),
        '/part-2': Part2(),
    ];
    

    And in this case, if you navigate to /page-two/part-1 then it would load PageTwo(), and it would load Part1() wherever you specified <app-route></app-route> on PageTwo(). I don't understand how one would do this in Flutter because in Flutter it seems like you can only ever have a single flat route in your main.dart (in your MaterialApp builder)

    The best thing I can think of is to have a variable on PageTwo(), and have a type of switch statement:

    switch (subPage) {
       case '/part-1':
           return Part1();
       case '/part-2':
           return Part2();
    }
    

    But this seems like a crappy solution. You also now have the problem of fixing animations etc yourself (because the MaterialApp won't help you here automatically).

    Here is something about this but this seems super complicated for a noob. Is this really the right/only way to do this: Nesting routes with flutter