Path
The Path Module is designed to streamline navigation and data passing in Flutter Web projects or APIs. By enabling the definition of routes that associate specific URLs with corresponding widgets or tasks, the Path Module ensures that users are directed to the right part of the application based on the URL accessed. This module is invaluable for developers looking to create well-structured navigation systems and enhance the dynamic nature of their applications.
Route
A Route
is an abstract class that you can extend to define your application's routes. It serves three primary purposes:
-
Define fields: You can define both segment properties and query properties which will be set based on a path. Segment properties are based on an actual segment of the path, such as
[userId]
in/user/[userId]
, whereas query properties are additional properties in addition to the segments themselves, such asview
in/user/[userId]?view=public
. -
Define a
PathDefinition
: ThePathDefinition
specifies what the path will look like and determines whether theRoute
matches a given path. It can include predefined strings or properties. -
Define how to instantiate the class: This is necessary because every time you navigate to a
Route
, you are returned a copy of theRoute
with all the fields filled in with the correct values.
Here's an example of a Route
that takes a name
from the path itself and consumes a repeat
query property.
class GreetRoute with IsRoute<GreetRoute> {
late final nameProperty = field<String>(name: 'name').required(); // Contains the non-nullable `name` passed into the route.
late final repeatProperty = field<int>(name: 'repeat').withFallback(() => 1); // If no `repeat` is given as a query parameter, it will default the value to `1`.
@override
PathDefinition get pathDefinition => PathDefinition.string('greet').property(nameProperty); // The path this handles is `/greet/[name]`.
@override
List<RouteProperty> get queryProperties => [repeatProperty]; // Consumes and casts `repeat` from the query parameters, such as `?repeat=3`.
@override
GreetRoute copy() {
return GreetRoute();
}
}
Fields
You can create fields in a Route
by using a late field with the field
helper. Define the type of the field in the generic and pass along the name of the field. The name
is used to determine where to pull values from the query parameters.
The field value will be coerced from the path, so you can define int
and double
fields and get their type-coerced values. If the value from the path cannot be coerced to the specified type, an exception is thrown.
You can add modifiers to a field, such as .required()
, to extend their functionality. Here are the modifiers currently available:
.required()
: Makes the field non-nullable. If the field isnull
when the Route is created, it will throw an exception..withFallback()
: If the field isnull
when the Route is created, it will use a fallback value instead.
PathDefinition
A PathDefinition
defines what the path will look like and determines whether a given URL matches the path. It can include predefined strings or properties. For example:
You can use .string()
to define a new string segment and .property()
to define an arbitrary value that fills in a property.
For example:
PathDefinition.string('first').string('second') // matches `/first/second`
PathDefinition.string('user').property(userIdProperty) // matches `/user/[userId]` where `userIdProperty` is a field in the Route itself.
PathDefinition.string('user').property(userIdProperty).string('edit') // matches `/user/[userId]/edit` where `userIdProperty` is a field in the Route itself.
Query Properties
For optional properties you want to retrieve from a path, such as ?myProperty=hi
, add the property to the queryProperties
getter, and the Route
will find all query properties from the path and fill them in.
class TestRoute with IsRoute<TestRoute> {
late final myProperty = field<String>(name: 'myProperty');
@override
List<RouteProperty> get queryProperties => [myProperty];
...
}
Hidden Properties
If you want to instantiate a Route but provide it with more dynamic field values without inserting them into the path itself, you can add those properties to the hiddenProperties
getter. The Route
will fill them in accordingly.
class TestRoute with IsRoute<TestRoute> {
late final passwordProperty = field<String>(name: 'password');
@override
List<RouteProperty> get hiddenProperties => [passwordProperty];
...
}
context.navigateTo(TestRoute()..passwordProperty.set('hunter2'));
Usage
Route
s are used in the Flutter AppPondContext to define the URLs that can be navigated to. The AutomatePondContext uses AutomatePathDefinition
, which is heavily inspired by the Path Module, to define the routes of the CLI commands that can be used. Eventually, the Path Module will be used to define the routes for backend APIs as well.