Dataform

A Flutter package to fetch data from a form as a Map.
With this package, you don't need to manage a lot of text controllers in a form anymore! Simply call a function when the users tap the button at the end of your form and get all the data in a Map, ready to be transformed into JSON and sent to an API!

Usage

Scaffold(
  // Wrap your form in a DataForm widget. No need to use Form from Flutter
  body: DataForm(  
    builder: (context) {
      return Column(
        children: [
          // The [id] is used to identify the field in the [Map]. The [id] must be
          // unique for each field and contain "/" if you want to nest the field
          // inside the map. Example, fields with the following ids:
          //
          //
          // * user/name
          // * user/age
          // * user/address/street
          // * user/address/number
          // * admin
          //
          //
          // will result in the following map:
          //
          // 
          // {
          //   "user": {
          //     name: "...",
          //     age: "...",
          //     address: {
          //       street: "...",
          //       number: "...",
          //     }
          //   },
          //  "admin": "...",
          // }
          // 
          //
          DataFormTextField(
            id: 'user/name',
            decoration:
                const InputDecoration.collapsed(hintText: 'User name'),
            validator: (value) {
              return value == null || value.isEmpty ? 'Error' : null;
            },
          ),
          const SizedBox(height: 20),
          const DataFormTextField(
            decoration: InputDecoration.collapsed(hintText: 'User email'),
            id: 'user/email',
          ),
          const SizedBox(height: 20),
          DataFormTextField(
            decoration:
                const InputDecoration.collapsed(hintText: 'User age'),
            id: 'user/age',
            formatter: (value) => int.tryParse(value ?? '') ?? -1,
            // You can optionally pass a validate function that returns a map
            // where the keys are conditions and the values are error strings
            // that will be displayed if the condition is false. Example:
            //
            // value must not be null otherwise display 'Value cannot be null!'
            //
            // int.tryParse(value) must return a number no null
            // otherwise display 'Value must be a number!'
            validate: (value) => {
              value != null: 'Value cannot be null!',
              int.tryParse(value ?? '') != null: 'Value must be a number!',
            },
          ),
          const SizedBox(height: 20),
          const DataFormTextField(
            decoration: InputDecoration.collapsed(hintText: 'User city'),
            id: 'user/location/city',
          ),
          const SizedBox(height: 20),
          const DataFormTextField(
            decoration: InputDecoration.collapsed(hintText: 'User state'),
            id: 'user/location/state',
          ),
          const SizedBox(height: 20),
          const DataFormTextField(
            decoration: InputDecoration.collapsed(hintText: 'Password'),
            obscureText: true,
            id: 'password',
          ),
          const SizedBox(height: 20),
          const DataFormCheckbox(
            id: 'admin',
            text: 'Admin',
          ),
          const SizedBox(height: 20),
          const DataFormSwitch(
            id: 'remember',
            active: true,
            text: 'Remember',
          ),
          const SizedBox(height: 20),
          // You can create your custom form fields by wrapping them in a
          // DataFormField widget.
          const DataFormField(
            id: 'space',
            value: 20,
            child: SizedBox(width: 20),
          ),
          const SizedBox(height: 30),
          ElevatedButton(
            child: const Text('SEND FORM'),
            onPressed: () {
              // When the user presses the button, the data will be validated
              // and if it's valid, the data will generate a map. Otherwise,
              // fetchData will return null.
              // The form above will generate the following map:
              //
              // {
              //   "user": {
              //     "name": "...",
              //     "email": "...",
              //     "age": 00,
              //     "location": {
              //       "city": "...",
              //       "state": "...",
              //     }
              //   },
              //   "admin": false,
              //   "password": "...",
              //   "remember": true,
              //   "space": 20,
              // }
              //
              // Now, if you want to send this data to an api as JSON,
              // you can simply call json.encode(data); No need to
              // manage a lot of text controllers anymore.
              Map<String, dynamic>? data =
                  DataFormState.of(context).fetchData();
              if (kDebugMode) {
                print(data);
              }
            },
          )
        ],
      );
    },
  ),
);

Installation

Add the following line to pubspec.yaml:

dependencies:
  dataform: ^1.0.3

Libraries

dataform