Skip to content

Session & Flash Data

View raw .md

The Session facade provides flash data that survives exactly one navigation hop, letting you pass form input and validation errors across a back-navigation without temporary controller state.

On this page

Introduction#

The Session facade provides Laravel-style flash data that survives exactly one navigation hop. Use it to repopulate a form after a failed submit and a back navigation without wiring temporary state through controllers, the router, or global singletons.

The store has two buckets: the current bucket (readable by the view being built right now) and the next bucket (being collected by the currently-active handler). A call to Session.tick() promotes next into current, so flashed data is visible on exactly one frame.

Flashing Input#

Flash a map of values before navigating away:

dart
Session.flash({
  'name': 'John',
  'email': '[email protected]',
});
MagicRoute.back();

Flashing Errors#

Flash per-field error messages:

dart
Session.flashErrors({
  'email': ['The email has already been taken.'],
});

Reading Old Input#

In the form view, repopulate via the old() helper:

dart
WFormInput(
  initialValue: old('email') ?? '',
);

if (Session.hasError('email'))
  WText(Session.error('email')!, className: 'text-red-500');

Session.oldRaw(field) returns the original typed value (booleans, numbers, custom objects) instead of stringifying it.

Automatic Flash in MagicFormData#

MagicFormData.validate() automatically flashes the current form data when validation fails, so you never need to wire it manually:

dart
void _submit() {
  if (!form.validate()) return; // form data is auto-flashed on failure
  controller.register(form.data);
}

After a back navigation and a Session.tick(), old('email') returns the last-submitted value.

Advancing the Flash Bucket#

Flash data survives exactly one navigation. Advance the bucket only when the router location actually changes. Do not wire Session.tick directly to the router delegate listener: the delegate can notify for more than real navigation (redirect re-evaluation, notifier rebuilds) and would expire flash data prematurely.

dart
var lastLocation = MagicRouter.instance.currentLocation;

MagicRouter.instance.routerConfig.routerDelegate.addListener(() {
  final currentLocation = MagicRouter.instance.currentLocation;
  if (currentLocation == lastLocation) return;
  lastLocation = currentLocation;
  Session.tick();
});

Place this in a ServiceProvider.boot() after Magic.init() completes.

Testing#

In tests, always reset the store in setUp():

dart
setUp(() {
  MagicApp.reset();
  Magic.flush();
  Session.reset();
});

Swap the backing store with a custom SessionStore via Session.setStore(store) if you need isolated buckets per test group.

esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.