Flutter web: Navigating URLs using named routes
👉 Update: Flutter’s new Navigation and Routing system is now available, and it is the preferred way to handle URLs in Flutter.
Named routes can be used to navigate between pages inside a Flutter mobile app, but they also work for URLs in Flutter web apps. This article explains how to add named routes to your app, and how you can customize them, to have pattern matching inside the routes.
Defining named routes
Named routes can be added to your application by defining them within the
MaterialApp class. The
MaterialApp.routes property contains a map listing each named route and its associated display widget. The
MaterialApp.initialRoute property determines what route displays as the application starts. The
initialRoute thus needs to be defined inside of the
routes property. For example:
A good practice to keep your code organized is to put named routes inside static variables, for example, on the widgets themselves:
MaterialApp.routes with the named routes now defined as static variables:
Navigating between pages
To navigate from one page to another, simply push the named route to the navigator:
See a full interactive example of this on DartPad. If you build and run the application yourself for the web, you can also just type in
/#/overview inside the web browser. This pushes the route named overview to the
Navigator, and takes you to the
OverviewPage widget, as you can see in the following GIF:
Routing logic for dynamic URLs
You may need to address more complex scenarios then addressed here, such as having pattern matching inside the routes to allow for dynamic URLs. To extend this example, assume that you have many different articles on the overview page. For each article you want to be able to navigate directly via URLs:
To define named routes for all of the articles within the
MaterialApp does not scale very well. For such dynamic cases you need to do something more custom. As of this writing, the stable channel of Flutter is at v1.12, and there is no simple way to do this, though there are plans to add support for more advanced routing with the new Navigator.
For now you can use an external package, for example the Fluro package provides more advanced routing. It gives you wildcard pattern matching in routes, as well as parsing for query strings in URLs. There are probably many other available packages, so please leave a comment with the name of your favorite.
If you are up for the challenge, you can also get dynamic routes by making use of the
MaterialApp.onGenerateRoute property. Use this to write routing logic for when a named route is not inside of
For each route, define a
Path with a
RegEx pattern. If the named route matches the pattern, return the associated widget. Next, define the
Path class to support that:
For the overview page and the home route, it is quite simple and looks similar to what you had before. The following example creates a
RegEx pattern that matches a slug (lowercase letters with a dash) that is used to find the corresponding article:
All that remains is to create an
onGenerateRoute function for
MaterialApp. If the current named route (
settings.name) is defined in the paths list, return the associated widget. Make sure to pass any named matches in the
RegEx (in this example it is the slug). If no matches are found, simply return null,
WidgetsApp.onUnknownRoute is called to handle such cases:
Make sure to define the
onGenerateRoute function inside the
MaterialApp class; you have implemented dynamic URLs with Flutter, using named routes! You can see a full interactive example on DartPad.
Whether you choose to write your own custom logic for routes, or simply use the routes support that exists within
MaterialApp, you get URL support by default with a Flutter app on the web, when using named routes. Implementing named routes can also ensure that you decouple the presentation logic from the routing logic, which leads to less code duplication.
Let me know in the comments what solution you use in your app, whether it is writing your own custom logic or using an external package.