dynamic_pages 0.1.0 copy "dynamic_pages: ^0.1.0" to clipboard
dynamic_pages: ^0.1.0 copied to clipboard

Schema-driven, type-safe generated Flutter pages for Dart models.

dynamic_pages #

Build production-oriented Flutter forms from typed Dart/Freezed models or a constrained server schema. The generator emits typed metadata and a small page wrapper; maintained runtime widgets handle rendering, validation, loading, errors, and themes.

Version 0.1 focuses deliberately on forms. Details, list, and CRUD page renderers can be added without changing the schema-first architecture.

Features #

  • source_gen support for regular Dart and Freezed factory models
  • text, email, number, date, enum dropdown, checkbox, and custom fields
  • create and edit modes through initialValue
  • synchronous and asynchronous validation
  • loading state and API field-error mapping
  • scroll to the first invalid field
  • dirty-state confirmation
  • application-wide and per-page themes
  • custom field builders plus header and footer composition
  • constrained JSON schemas for server-driven forms

Typed model generation #

Add dynamic_pages and your preferred model packages, then add build_runner to dev_dependencies.

import 'package:dynamic_pages/dynamic_pages.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'user_form.freezed.dart';
part 'user_form.g.dart';

enum Role { admin, member }

@freezed
@GenerateFormPage(title: 'Create user', submitLabel: 'Save')
abstract class UserForm with _$UserForm {
  const factory UserForm({
    @FormTextField(label: 'Name', required: true, minLength: 2)
    required String name,

    @FormEmailField(label: 'Email', required: true)
    required String email,

    @FormDateField(label: 'Birth date')
    DateTime? birthDate,

    @FormDropdownField(label: 'Role', source: Role.values)
    required Role role,

    @FormCheckboxField(label: 'Receive product updates')
    @Default(false)
    bool receiveUpdates,
  }) = _UserForm;
}

Generate both the Freezed implementation and page metadata:

dart run build_runner build --delete-conflicting-outputs

The generated UserFormPage has a typed submit callback:

UserFormPage(
  initialValue: existingUser,
  onSubmit: (value) async {
    await repository.save(value);
  },
);

You can also render the generated schema directly:

ModelFormPage<UserForm>(
  schema: userFormPageSchema,
  onSubmit: repository.save,
);

Themes #

Use Flutter's extension mechanism for application-wide defaults:

MaterialApp(
  theme: ThemeData(
    extensions: const [
      DynamicPageThemeData(
        contentMaxWidth: 640,
        contentPadding: EdgeInsets.all(32),
        fieldSpacing: 20,
      ),
    ],
  ),
);

Any page can override only the tokens it needs:

UserFormPage(
  theme: const DynamicPageThemeData(
    contentMaxWidth: 520,
    fieldSpacing: 12,
  ),
  onSubmit: repository.save,
);

Themes resolve in this order: package fallback, application ThemeData.extensions, then the page override.

Custom fields and composition #

UserFormPage(
  header: const ProfileHeader(),
  footer: const TermsSection(),
  fieldBuilders: {
    'avatar': (context, data) => AvatarPicker(
      value: data.value,
      errorText: data.errorText,
      onChanged: data.onChanged,
    ),
  },
  onSubmit: repository.save,
);

Annotate non-standard values with @CustomFormField so missing builders are reported clearly in the UI.

Server-driven forms #

Server schemas use a small domain vocabulary rather than arbitrary Flutter widgets:

DynamicSchemaPage.fromJson(
  schema: {
    'type': 'form',
    'title': 'Create user',
    'submitLabel': 'Save',
    'theme': {
      'contentWidth': 'narrow',
      'density': 'comfortable',
    },
    'fields': [
      {
        'key': 'email',
        'type': 'email',
        'label': 'Email',
        'required': true,
      },
      {
        'key': 'role',
        'type': 'dropdown',
        'label': 'Role',
        'options': [
          {'value': 'admin', 'label': 'Administrator'},
          {'value': 'member', 'label': 'Member'},
        ],
      },
    ],
  },
  data: responseData,
  onSubmit: api.saveDynamicForm,
);

Supported server theme tokens are constrained widths, density, and padding. Unknown page and field types throw FormatException.

Mapping API errors #

Throw FormSubmissionException from a submit callback:

throw const FormSubmissionException(
  {
    'email': ['Email is already registered'],
  },
  message: 'Please correct the highlighted fields.',
);

The renderer assigns each message to the matching field and scrolls to the first error.

0
likes
0
points
0
downloads

Publisher

verified publisherpinz.dev

Weekly Downloads

Schema-driven, type-safe generated Flutter pages for Dart models.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

analyzer, build, flutter, source_gen

More

Packages that depend on dynamic_pages