championforms 0.0.4 copy "championforms: ^0.0.4" to clipboard
championforms: ^0.0.4 copied to clipboard

Easy Build Data Input Fields of All Types in Flutter

example/lib/main.dart

import 'package:championforms/championforms.dart';
import 'package:championforms/controllers/form_controller.dart';
import 'package:championforms/models/formfieldbase.dart';
import 'package:championforms/models/formresults.dart';
import 'package:championforms/models/multiselect_option.dart';
import 'package:flutter/material.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // TRY THIS: Try running your application with "flutter run". You'll see
        // the application has a purple toolbar. Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot
        // reload" button in a Flutter-supported IDE, or press "r" if you used
        // the command line to start the app).
        //
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot
        // restart instead.
        //
        // This works for code too, not just values: Most code changes can be
        // tested with just a hot reload.
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late ChampionFormController controller;

  @override
  void initState() {
    super.initState();
    controller = ChampionFormController();
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  void _executeLogin() {
    // Because championforms relies on riverpod. Field results
    // are accessible anywhere in the app as long as the form is still active.
    // You can simply build the FormResults object at any time to cause the form
    // to pass results and run validation.
    final FormResults results = FormResults.getResults(controller: controller);

    // Once run the form will tell you if it is in an error state.
    // If true, then stop processing.
    final errors = results.errorState;
    debugPrint("Current Error State is: $errors");
    if (errors == false) {
      // No errors, excellent!
      // Fields can be "grabbed" from the results by their ID.
      // Then you can format them .asString(), asStringList(), asMultiSelectList()
      debugPrint(results.grab("Email").asString());
      debugPrint(results.grab("DropdownField").asString());
      debugPrint(results
          .grab("SelectBox")
          .asMultiselectList()
          .map((field) => field.value)
          .join(", "));
    } else {
      debugPrint("The form had some errors.");
      debugPrint(results.formErrors
          .map((error) =>
              "Field ${error.fieldId} had the error: ${error.reason}")
          .join(", "));
    }
  }

  @override
  Widget build(BuildContext context) {
    // Time to build a sample form:
    final List<FormFieldBase> fields = [
      ChampionTextField(
        id: "Email", // To ID the field, must be unique per form
        validateLive:
            true, // This causes the field to validate itself as soon as it loses focus -- defaults to false.
        maxLines: 1, // Forces field to one line
        hintText: "Email", // Hint text in the text field
        textFieldTitle:
            "Email", // This is the title which displays in the field until you click on it, then moves to the border
        description:
            "Enter your email Address", // Description by default displays above the field below the title
        // Validators are a list of FormBuilderValidator objects which run a bool function on the results to determine if the input is satisfactory.
        // Default validators are provided in the DefaultValidators() object. The most important one there is the dependency on valid emails.
        // If a field isn't valid, then the field state is set to error causing the colors to change and the error is displayed (by default) below the field in errorBorder color.
        validators: [
          FormBuilderValidator(
            validator: (results) => DefaultValidators().isEmpty(results),
            reason: "Field is empty",
          ),
          FormBuilderValidator(
            validator: (results) => DefaultValidators().isEmail(results),
            reason: "This isn't an email address",
          ),
        ],
        // Leading icon. Can make clickable with MouseRegion, and GestureDetector
        leading: const Icon(Icons.verified_user),
      ),
      ChampionTextField(
          id: "Text Field 1",
          textFieldTitle: "Password",
          maxLines: 1,
          password: true, // Password being true obscures the text in the field
          validateLive: true,

          // The onSubmit will fire when the user presses enter.
          // If maxLines is null or set to a larger number then onSubmit will fire on enter and
          // new line will be triggered on shift + enter.
          // If no onSubmit is present, then enter will add a new line as normal.
          onSubmit: (results) => debugPrint("Login"),
          validators: [
            FormBuilderValidator(
                validator: (results) => DefaultValidators().isEmpty(results),
                reason: "Password is Empty"),
          ],
          leading: const Icon(Icons.password)),

      // Champion option fields utilize a builder to handle the elements in the field.
      // Currently, this is the base implementation which spits out a Dropdown.
      // The setup should work for any multi-select object being used.
      // Custom builders can be inserted via the fieldBuilder property.
      // See the widgets_external/field_builders/checkboxfield_builder.dart file for details
      // on constructing your own custom builder.
      ChampionOptionSelect(
          id: "DropdownField", // ID can be anything but should be unique
          title: "Quick Dropdown",
          // MultiselectOption by default will pass through the label and value when the form is submitted.
          // However the additionalData property will accept any object? allowing you to pass through any element you desire to the formResults.
          options: [
            MultiselectOption(
              label: "Option 1",
              value: "Value 1",
            ),
            MultiselectOption(
              label: "Option 2",
              value: "Value 2",
            ),
            MultiselectOption(
              label: "Option 3",
              value: "Value 3",
            ),
            MultiselectOption(
              label: "Option 4",
              value: "Value 4",
            ),
          ]),
      // ChampionCheckboxSelect extends ChampionOptionSelect simply swapping out the fieldBuilder
      // For one which displays the options as checkboxes.
      ChampionCheckboxSelect(
        id: "SelectBox",
        requestFocus: true,
        multiselect: true,
        validateLive: true,
        validators: [
          FormBuilderValidator(
              validator: (results) => DefaultValidators().isEmpty(results),
              reason: "Nothing is checked"),
        ],

        title: "Choose your weapon",
        //defaultValue: ["Hiya"],icon: const Icon(Icons.title),
        leading: const MouseRegion(
            cursor: SystemMouseCursors.click, child: Icon(Icons.mic)),
        trailing: const Icon(Icons.search),

        options: [
          MultiselectOption(value: "Hi", label: "Hello"),
          MultiselectOption(value: "Hiya", label: "Wat"),
          MultiselectOption(value: "Yoz", label: "Sup"),
        ],
      ),
    ];

    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: const Text("Champion Forms Example"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // The ChampionForm widget actually displays a form.
            // Throw in the fields defined above.
            // The ID keeps forms seperate when pulling results.
            // If two forms have the same ID and different fields, then all fields
            // will appear in the results when the form is evaluated.
            ChampionForm(
              theme: softBlueColorTheme(context),
              controller: controller,
              spacing: 10,
              fields: fields,
            ),
            ElevatedButton(
                child: const Text("Set Values"),
                onPressed: () {
                  controller.updateTextFieldValue("Email", "Hello@hello.com");
                  controller.toggleMultiSelectValue("DropdownField", toggleOn: ["Value 3", "Value 2"]);
                  controller.toggleMultiSelectValue(
                    "SelectBox",
                    toggleOn: ["Hi", "Yoz"],
                    toggleOff: ["Hiya"],
                  );
                }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _executeLogin,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
2
likes
130
points
77
downloads

Publisher

unverified uploader

Weekly Downloads

Easy Build Data Input Fields of All Types in Flutter

Homepage
Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

collection, dotted_border, email_validator, flutter, super_clipboard, super_drag_and_drop, textfield_tags, uuid

More

Packages that depend on championforms