skip to Main Content

I have created a custom widget to get input from the user. I am using TextFields and TextEditingController to get this input. Here is the code for the custom widget called NewAddress:

import 'package:flutter/material.dart';

class NewAddress extends StatefulWidget {
  const NewAddress({super.key}); // this is the constructor

  @override
  State<NewAddress> createState() {
    return _NewAddressState();
  }
}

class _NewAddressState extends State<NewAddress> {
  final _address1Controller = TextEditingController();
  final _address2Controller = TextEditingController();
  final _cityController = TextEditingController();
  final _stateController = TextEditingController();
  final zipController = TextEditingController();

  @override
  void dispose() {
    _address1Controller.dispose();
    _address2Controller.dispose();
    _cityController.dispose();
    _stateController.dispose();
    zipController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20),
      child: Column(
        children: [
          TextField(
            keyboardType: TextInputType.streetAddress,
            controller: _address1Controller,
            decoration: const InputDecoration(
              label: Text(
                'Address 1',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ),
          TextField(
            keyboardType: TextInputType.streetAddress,
            controller: _address2Controller,
            decoration: const InputDecoration(
              label: Text(
                'Address 2',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ),
          TextField(
            keyboardType: TextInputType.text,
            controller: _cityController,
            decoration: const InputDecoration(
              label: Text(
                'City',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ),
          TextField(
            keyboardType: TextInputType.text,
            controller: _stateController,
            decoration: const InputDecoration(
              label: Text(
                'State',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ),
          TextField(
            keyboardType: TextInputType.number,
            controller: zipController,
            decoration: const InputDecoration(
              label: Text(
                'Zip',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

I use this widget in the initial app screen called StartScreen. Here is the code for StartScreen:

import 'package:flutter/material.dart';
import '../screens/widgets/address_input.dart';
import '../screens/data_screen.dart';

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const NewAddress(),
          OutlinedButton.icon(
            onPressed: () {
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => DataScreen(zipController.text)));
            },
            style: OutlinedButton.styleFrom(
                backgroundColor: Colors.blue, alignment: Alignment.center),
            icon: const Icon(Icons.dataset, color: Colors.black, size: 30),
            label: const Text(
              'GET PROPERTY',
              style: TextStyle(color: Colors.black, fontSize: 30),
            ),
          ),
        ],
      ),
    );
  }
}

I am getting an error on this line before I run the code: MaterialPageRoute(
builder: (context) => DataScreen(zipController.text)));
The line is under zipController and here is the error message: "Undefined name ‘zipController’."
I think I am getting it because I am not accessing the zipController in the right way.

I have tried this: MaterialPageRoute(
builder: (context) => DataScreen(NewAddress.zipController.text)));
but I still get an error but this time this is the error message:
The getter ‘zipController’ isn’t defined for the type ‘NewAddress’.
but as you can see in the code, I have imported the file where NewAddress and zipController are defined.

What am I doing wrong?

2

Answers


  1. The issue you’re facing is related to how you’re trying to access the zipController variable from the NewAddress class. The zipController is an instance variable of the _NewAddressState class within the NewAddress widget, so you can’t directly access it using the widget class itself.

    Instead, you need to pass the zipController instance to the DataScreen widget when you create it. Here’s how you can modify your code to achieve this:

    Add a constructor to your NewAddress widget to pass the zipController to the parent widget (in this case, StartScreen).

     class NewAddress extends StatefulWidget {
       final TextEditingController zipController;
       const NewAddress({Key? key, required this.zipController}) : super(key: key);
    }
    

    Modify your StartScreen widget to pass the zipController to the NewAddress widget.

    class StartScreen extends StatelessWidget {
     final TextEditingController zipController = TextEditingController();
    
     @override
     Widget build(BuildContext context) {
      return Center(
       child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          NewAddress(zipController: zipController), // Pass zipController here
          OutlinedButton.icon(
            onPressed: () {
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => DataScreen(zipController.text)));
            },
            style: OutlinedButton.styleFrom(
                backgroundColor: Colors.blue, alignment: Alignment.center),
            icon: const Icon(Icons.dataset, color: Colors.black, size: 30),
            label: const Text(
              'GET PROPERTY',
              style: TextStyle(color: Colors.black, fontSize: 30),
            ),
          ),
        ],
      ),
    );
    }
    }
    

    Bypassing the zipController instance to the NewAddress widget and then using it to create the DataScreen widget, you should be able to resolve the "Undefined name ‘zipController’" error. This way, you’re maintaining the proper scope for the zipController variable.

    Login or Signup to reply.
  2. You should do something few changes. I added comments on what you should change. Customize everything as yourself.

    class StartScreen extends StatelessWidget {
      const StartScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        final TextEditingController zipData = TextEditingController();  // add controller here
        
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                NewAddress(
                  zipData: zipData, //pass every controller by this
                ),
                OutlinedButton.icon(
                  onPressed: () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => DataScreen(
                                  zipData: zipData.text,
                                )));//and also pass in other page
                  },
                  style: OutlinedButton.styleFrom(
                      backgroundColor: Colors.blue, alignment: Alignment.center),
                  icon: const Icon(Icons.dataset, color: Colors.black, size: 30),
                  label: const Text(
                    'GET PROPERTY',
                    style: TextStyle(color: Colors.black, fontSize: 30),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    Here is your NewAddress widget. I showed here only one example.

    class NewAddress extends StatelessWidget {
      const NewAddress(
          {super.key, required this.zipData}); // this is the constructor
      final TextEditingController zipData;
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(20),
          child: Column(
            children: [
              TextField(
                keyboardType: TextInputType.streetAddress,
                controller: zipData,
                decoration: const InputDecoration(
                  label: Text(
                    'Address 1',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    And finally, your DataScreen should be like this.

    class DataScreen extends StatelessWidget {
      const DataScreen({super.key, required this.zipData});
      final String zipData;
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Text(zipData),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search