Routing 2: Add New Dog Page

The only other page we will create is to add dogs.

The next section will show you how to handle user input, but you might as well add that route now, while we're on the subject.

1. Add NewDogPage

Create a new file in the lib folder called new_dog_form.dart.

The UI of this page is simple:

form page screen shot

Here's the code with no functionality (again, you'll add the user input functionality in the next section):

// new_dog_form.dart

import 'package:flutter/material.dart';

class AddDogFormPage extends StatefulWidget {
  
  _AddDogFormPageState createState() => _AddDogFormPageState();
}

class _AddDogFormPageState extends State<AddDogFormPage> {
  
  Widget build(BuildContext context) {
    // new page needs scaffolding!
    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),
                // Text Field is the basic input widget for Flutter.
                // It comes built in with a ton of great UI and
                // functionality, such as the labelText field you see below.
                child: TextField(
                    decoration: InputDecoration(
                  labelText: 'Name the Pup',
                )),
              ),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: TextField(
                    decoration: InputDecoration(
                  labelText: "Pup's location",
                )),
              ),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: TextField(
                  decoration: InputDecoration(
                    labelText: 'All about the pup',
                  ),
                ),
              ),
              // A Strange situation.
              // A piece of the app that you'll add in the next
              // section *needs* to know its context,
              // and the easiest way to pass a context is to
              // use a builder method. So I've wrapped
              // this button in a Builder as a sort of 'hack'.
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Builder(
                  builder: (context) {
                    // The basic Material Design action button.
                    return RaisedButton(
                      // If onPressed is null, the button is disabled
                      // this is my goto temporary callback.
                      onPressed: () => print('PRESSED'),
                      color: Colors.indigoAccent,
                      child: Text('Submit Pup'),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

2. Add the Routing

Like the last section, you now have a page that you can't access. Add the button and routing information to the _MyHomePageState class.

// main.dart


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
      backgroundColor: Colors.black87,
      // This is how you add new buttons to the top right of a material appBar.
      // You can add as many as you'd like.
      actions: [
         IconButton(
          icon: Icon(Icons.add),
          onPressed: _showNewDogForm,
        ),
      ],
    ),
  ...

That will add a plus-sign looking button to the top right corner of your app, and finally you can add the method that builds a new route.

Import new_dog_form.dart in main.dart:

// main.dart

import 'package:flutter/material.dart';

import 'dog_list.dart';
import 'dog_model.dart';
import 'new_dog_form.dart';

Add this anywhere in your _MyHomePageState class:

// Any time you're pushing a new route and expect that route
// to return something back to you,
// you need to use an async function.
// In this case, the function will create a form page
// which the user can fill out and submit.
// On submission, the information in that form page
// will be passed back to this function.
Future _showNewDogForm() async {
  // push a new route like you did in the last section
  Dog newDog = await Navigator.of(context).push(
    MaterialPageRoute(
      builder: (BuildContext context) {
        return AddDogFormPage();
      },
    ),
  );
  // A null check, to make sure that the user didn't abandon the form.
  if (newDog != null) {
    // Add a newDog to our mock dog array.
    initialDoggos.add(newDog);
  }
}