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

Headless, controller-free, declarative form engine for Flutter and Dart.

example/lib/main.dart

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: RegistrationFormPage(),
    );
  }
}

class RegistrationFormPage extends StatefulWidget {
  const RegistrationFormPage({super.key});

  @override
  State<RegistrationFormPage> createState() => _RegistrationFormPageState();
}

class _RegistrationFormPageState extends State<RegistrationFormPage> {
  late final FormEngine form;

  @override
  void initState() {
    super.initState();

    form = FormEngine(
      schema: FormSchema(
        fields: {
          'fullName': FieldSchema<String>.withValidators(
            validators: Validators()
                .required()
                .alphaSpace()
                .minLength(3)
                .maxLength(50),
          ),
          'username': FieldSchema<String>.withValidators(
            validators: Validators()
                .required()
                .alpha()
                .minLength(3)
                .maxLength(20),
          ),
          'email': FieldSchema<String>.withValidators(
            validators: Validators().required().email(),
          ),
          'phone': FieldSchema<String>.withValidators(
            validators: Validators()
                .required()
                .numeric()
                .minLength(10)
                .maxLength(10),
          ),
          'password': FieldSchema<String>.withValidators(
            validators: Validators()
                .required()
                .minLength(8)
                .maxLength(32)
                .regex(
                  RegExp(r'^(?=.*[A-Z])(?=.*\d).*$'),
                  message:
                      'Password must contain at least one uppercase letter and one number',
                ),
          ),
          'website': FieldSchema<String>.withValidators(
            validators: Validators().url(),
          ),
        },
      ),
    );
  }

  void _submit() {
    final isValid = form.validateAll();

    setState(() {});

    if (isValid) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Registration successful:\n${form.state.values}'),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    final errors = form.state.errors;

    return Scaffold(
      appBar: AppBar(title: const Text('Registration')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            _field(
              label: 'Full Name',
              error: errors['fullName'],
              onChanged: (v) => _update('fullName', v),
            ),
            _field(
              label: 'Username',
              error: errors['username'],
              onChanged: (v) => _update('username', v),
            ),
            _field(
              label: 'Email',
              error: errors['email'],
              onChanged: (v) => _update('email', v),
            ),
            _field(
              label: 'Phone Number',
              keyboardType: TextInputType.phone,
              error: errors['phone'],
              onChanged: (v) => _update('phone', v),
            ),
            _field(
              label: 'Password',
              obscureText: true,
              error: errors['password'],
              onChanged: (v) => _update('password', v),
            ),
            _field(
              label: 'Website (optional)',
              error: errors['website'],
              onChanged: (v) => _update('website', v),
            ),
            const SizedBox(height: 24),
            ElevatedButton(onPressed: _submit, child: const Text('Register')),
          ],
        ),
      ),
    );
  }

  void _update(String field, String value) {
    setState(() {
      form.updateValue(field, value);
    });
  }

  Widget _field({
    required String label,
    required String? error,
    required ValueChanged<String> onChanged,
    TextInputType? keyboardType,
    bool obscureText = false,
  }) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 12),
      child: TextField(
        keyboardType: keyboardType,
        obscureText: obscureText,
        onChanged: onChanged,
        decoration: InputDecoration(
          labelText: label,
          errorText: error,
          border: const OutlineInputBorder(),
        ),
      ),
    );
  }
}
3
likes
160
points
155
downloads

Publisher

unverified uploader

Weekly Downloads

Headless, controller-free, declarative form engine for Flutter and Dart.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on form_engine