formx 0.5.0 copy "formx: ^0.5.0" to clipboard
formx: ^0.5.0 copied to clipboard

Build, validate and fill forms easily with extended Form and TextFormField.

Formx #

formx is a dynamic and robust Flutter package for building and managing forms. With an emphasis on ease of use and customizability, formx provides a powerful way to handle form inputs, validations, and submissions without the boilerplate.

Key Features #

  • Live State Management: Tracks changes to form fields in real-time, providing immediate feedback and interaction capabilities.
  • Built-in Validation: Enforces field requirements and custom validation logic, ensuring data integrity before submission.
  • Nested Forms Support: Easily manage complex forms with nested fields, allowing for structured data input and validation.
  • Initial Values Setup: Initialize form fields with default values, making edit forms and persisted states a breeze.
  • Custom Field Modifiers: Tailor the behavior of fields with custom modifiers, applying conditional logic or enhancing functionality.
  • Flexible Field Wrappers: Wrap fields with custom widgets for consistent styling or layout requirements across the form.
  • Decoration Customization: Modify the InputDecoration for each field to align with your app's theme and user experience design.
  • Error Handling: Customize the display of error messages with the possibility to use internationalization (i18n) for multi-language support.
  • Extensible API: Extend the base functionality with your own widgets and logic, maintaining a seamless integration with the form system.

Getting Started #

To integrate formx into your Flutter project, add the following dependency to your pubspec.yaml file:

dependencies:
  formx: ^latest_version

This package was made with Flutter in mind, and focus on having the simplest api as possible:

// For Form() just add change it to Formx()
 Form(...) -> Formx(...)

 // For TextFormField, add the `x` and your form `tag`. 
 // Your form value will be keyed to this tag.
 TextFormField(...) -> TextFormxField('tag', ...)

 // This also applies to states:
 final formxKey = GlobalKey<FormxState>();

Code example #

    return Scaffold(
      body: Formx(
        // Check your console and type, it's alive!
        onChanged: print,

        // Called when all fields are valid and submitted via Enter key or .submit().
        onSubmitted: (form) {
          if (Formx.at(context).validate()) {
            print('all valid and ready to go: $form');
          }
        },

        // Optional initial values for all fields. Tip: Model.toMap() or autofill.
        initialValues: const {
          'name': 'Big',
          'email': '',
          'address': {
            'street': 'Sesame Street',
            'number': 42, // will be stringified
          }
        },

        // Allows you to modify the field before it's built.
        fieldModifier: (tag, field) {
          // `.required()` is an extension. See [TextFormxFieldModifiers]
          return tag == 'name' ? field.required() : field;
        },

        // A wrapper that will be applied to all fields. DRY!
        fieldWrapper: (tag, widget) => Padding(padding: padding, child: widget),

        // [InputDecoration] callback. Tip: scope your form themes!
        decorationModifier: (tag, decoration) {
          return decoration?.copyWith(
            labelText: tag,
            border: const OutlineInputBorder(),
            constraints: const BoxConstraints(maxWidth: 300),
          );
        },

        // [TextFormField.validator] errorText callback. Tip: nice for i18n key.
        errorTextModifier: (tag, errorText) {
          if (tag == 'email') return errorText;
          return '$errorText.$tag';
        },

        // Your creativity is the limit. Manage your fields however you want.
        // Just make sure there's a [Formx] above them.
        child: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Text('USER'),

              // Same as TextFormField but copiable and const.
              const TextFormxField('name'),

              /// Stack validators through extensions modifiers.
              const TextFormxField('email')
                  .validate((value) => value.isNotEmpty) // same as .required()
                  .validate((value) => value.contains('form'))
                  .validate((value) => value.contains('x'), 'Missing x')
                  .validate((value) => value.contains('@'), 'Not an email'),

              /// Simple as one line.
              const TextFormxField('password'), // adds suffixIcon

              /// Nested fields too!?
              Formx(
                tag: 'address',

                /// and value modifier? Yes!
                valueModifier: (tag, value) {
                  if (tag == 'number') {
                    return int.tryParse(value);
                  }
                  return value;
                },
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Text('Address:'),

                    // Use copyWith to create your own extensions!
                    const TextFormxField('street').copyWith(),

                    // Like this cool num validator.
                    const TextFormxField('number').validateNum((n) => n < 100),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // You can use formxKey or just visit the state at context.
          final state = Formx.at(context); // or .of() for above.

          // Validate all fields. Just like `Form.validate()`.
          final isValid = state.validate();

          // you can also validate specific fields with:
          // validate(tag: , tags: , key: , keys: ,);

          if (isValid) {
            Map<String, dynamic> form = state.form;
            print('all valid and ready to go: $form');
          } else {
            print('invalid fields:');
            state.errorTexts.forEach((tag, errorText) {
              print('$tag: $errorText');
            });
          }
        },
        child: const Icon(Icons.check),
      ),
    );

Migrating from Vanilla Flutter Form and TextFormField #

Example with Flutter api #

  Form(
    child: Column(
      children: [
        TextFormField(
          onChanged: (value) => print('name'),
          decoration: InputDecoration(labelText: 'name'),
        ),
        TextFormField(
          onChangd: (value) => print('email'),
          decoration: InputDecoration(labelText: 'email'),
        ),
      ],
    ),
  )

Example with Formx api #

  Formx(
    onChanged: (form) => print(form),
    decorationModifier: (tag, decoration) => decoration?.copyWith(labelText: tag),
    child: const Column(
      children: [
        TextFormxField('name'),
        TextFormxField('email'),
      ],
    ),
  );

Contributing #

Contributions to formx are welcome! Whether it's bug reports, feature requests, or pull requests, all forms of collaboration can help make formx better for everyone.

8
likes
0
points
465
downloads

Publisher

verified publisherbranvier.com

Weekly Downloads

Build, validate and fill forms easily with extended Form and TextFormField.

Homepage

License

unknown (license)

Dependencies

flutter

More

Packages that depend on formx