Skip to content

A Full Form Example

Eray Erdin (&mut self) edited this page Jun 19, 2023 · 1 revision

ℹ️ The example in this page can be found in here.

Create a simple page with StatelessWidget.

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('my form page'),
      ),
    );
  }
}

In the body section, we will use StreamingFormBuilder.

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: StreamingFormBuilder(
        // we have a `builder` here
        builder: (context, controller, fieldFactory) {},
      ),
    );
  }
}

builder requires a function with three parameters:

  • context is there to access the BuildContext of our widget.
  • controller is an instance of StreamController instance from Dart's standard library. It streams Map<String, dynamic> where String is the key of each field and dynamic is the value.
  • fieldFactory is used to create a StreamController for a specific field. Any form field in builder method must use fieldFactory to create a StreamController. We will come back to it in the next example.

Let's populate some fields inside builder method.

return ListView(
  padding: const EdgeInsets.all(16),
  children: [
    // builds a `Text` to show JSON of all field values
    StreamBuilder(
      builder: (context, snapshot) {
        final data = snapshot.data ?? {};
        final raw = json.encode(data);

        return Center(
          child: Text(raw),
        );
      },
      // notice how we use `controller` from `builder` method
      // instead of creating our own
      stream: controller.stream,
    ),
    StreamingTextField(
      // notice that we create a `StreamController` with `getFieldController` method
      controller: fieldFactory.getFieldController('name'),
      decoration: const InputDecoration(labelText: 'Name'),
    ),
    StreamingTextField(
      controller: fieldFactory.getFieldController('surname'),
      decoration: const InputDecoration(labelText: 'Surname'),
    ),
    StreamingTextField(
      controller: fieldFactory.getFieldController('age'),
      decoration: const InputDecoration(labelText: 'Age'),
    ),
    const SizedBox(height: 8),
    Row(
      children: [
        StreamingSwitch(
            controller: fieldFactory.getFieldController('accept')),
        const Text('Accept the terms and conditions'),
      ],
    ),
  ],
)

In this example, you should notice a few things:

  • We have used a StreamBuilder and provided controller that is provided by builder method of StreamingFormBuilder. controller streams Map<String, dynamic> where String is the key of each field and dynamic is the value.
  • We have used fieldFactory.getFieldController method to create StreamController on each Streaming* form widgets. getFieldController does not only get a StreamController, but also registers it inside StreamingFormBuilder and listens to it. Whenever a change happens, it streams the new changes to StreamController on StreamingFormBuilder, which is Map<String, dynamic> as mentioned.
Clone this wiki locally