Forms 1: User Input

Adding functionality to your AddDogForm is a pretty easy feat.

Essentially, you just need to add a couple built in Flutter classes that keep track of form input, and a function that returns the data to the main page through the router.

1. TextEditingController class

There are a couple ways to go about tracking text input form elements. You can use Form widgets, or you can track each text input separately.

In this example, I will show you how to do the latter. TextEditingController is an important and fundamental thing in Flutter.

A TextEditingController is basically a class that listens to its assigned TextField, and updates it's own internal state every time the text in the TextField changes.

In your _AddDogFormPageState class, add a controller and onChanged property to each TextField:

// new_dog_form.dart

class _AddDogFormPageState extends State<AddDogFormPage> {
  // One TextEditingController for each form input:
  TextEditingController nameController = TextEditingController();
  TextEditingController locationController = TextEditingController();
  TextEditingController descriptionController = TextEditingController();

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add a new Dog'),
        backgroundColor: Colors.black87,
      ),
      body: Container(
        color: Colors.black54,
        child: Padding(
          padding: const EdgeInsets.symmetric(
            vertical: 8.0,
            horizontal: 32.0,
          ),
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: TextField(
                    // Tell your textfield which controller it owns
                    controller: nameController,
                    // Every single time the text changes in a
                    // TextField, this onChanged callback is called
                    // and it passes in the value.
                    //
                    // Set the text of your controller to
                    // to the next value.
                    onChanged: (v) => nameController.text = v,
                    decoration: InputDecoration(
                      labelText: 'Name the Pup',
                    )),
              ),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: TextField(
                    controller: locationController,
                    onChanged: (v) => locationController.text = v,
                    decoration: InputDecoration(
                      labelText: "Pups location",
                    )),
              ),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: TextField(
                    controller: descriptionController,
                    onChanged: (v) => descriptionController.text = v,
                    decoration: InputDecoration(
                      labelText: 'All about the pup',
                    )),
              ),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Builder(
                  builder: (context) {
                    return RaisedButton(
                      onPressed: () => print('PRESSED'),
                      color: Colors.indigoAccent,
                      child: Text('Submit Pup'),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Now, even though it doesn't look like anything new is happening, the TextEditingControllers are keeping track of your form.

2. Submit The Form

Import dog_model.dart into new_dog_form.dart:

// new_dog_form.dart

import 'package:flutter/material.dart';

import 'dog_model.dart';

In the same _AddDogFormPageState class, add the submitPup function, which will pass the form information back via the Navigator:

// new_dog_form.dart

// You'll need the context in order for the Navigator to work.
void submitPup(BuildContext context) {
  // First make sure there is some information in the form.
  // A dog needs a name, but may be location independent,
  // so we'll only abandon the save if there's no name.
  if (nameController.text.isEmpty) {
    print('Dogs need names!');
  } else {
    // Create a new dog with the information from the form.
    var newDog = Dog(nameController.text, locationController.text,
        descriptionController.text);
    // Pop the page off the route stack and pass the new
    // dog back to wherever this page was created.
    Navigator.of(context).pop(newDog);
  }
}

And lastly, add submitPup to your 'RaisedButton' onPressed callback:

// new_dog_form.dart

builder: (BuildContext context) {
  return RaisedButton(
    onPressed: () => submitPup(context),
    color: Colors.indigoAccent,
    child: Text('Submit Pup'),
  );
},

And that's that. Now, you should be able to submit a new dog and see it on your main page!