user9139407
user9139407

Reputation: 1022

TextFormField value is null

I tried to get TextFormField value. But result is null

main page,

children:[
  UrlTextField(),
  UsernameTextField(),
  UrlButton()
]

UrlTextField(), same like UsernameTextField()

class UrlTextField extends StatelessWidget {
  final myController = TextEditingController();
  @override
  Widget build(BuildContext context) {
    return AppTextField(
      decoration:
          InputDecoration(prefixText: "https://", labelText: "Enter your URL"),
      myController: myController,
      textInputType:  TextInputType.url,
    );}}

AppTextField() It's a common class, I used this class everywhere

class AppTextField extends StatelessWidget {
  final InputDecoration decoration;
  var myController = TextEditingController();
  final TextInputType textInputType;
  AppTextField({
    this.decoration,
    this.myController,
    this.textInputType
  });

  @override
  Widget build(BuildContext context) {
    return TextFormField(
        controller: myController,
        keyboardType: textInputType,
        textAlign: TextAlign.left,
        decoration: decoration
    );}}

I need to get Url and Username value when click button or any other area,

class UrlButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AppButton(
        onPressed: () {
          String url = UrlTextField().myController.text;
          String username = UsernameTextField().myController.text;
          print('url is $text');
        });}}

AppButton() This class also common

class AppButton extends StatelessWidget {
  final VoidCallback onPressed;
  AppButton({
    this.buttonTextStyle
  });

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text(...),
      onPressed: onPressed);}}

Upvotes: 0

Views: 4301

Answers (3)

kounex
kounex

Reputation: 1715

You are trying to retrieve text from a controller which has just been instantiated in the onPressed of the button so there can't be any text so far! To solve this problem you need some way of State Management to access and change an existing widget, in your case the UrlTextField widget. I will give you an example of how you could solve this quickly:

Main page:

class MainPage extends StatefulWidget {
    ...
    @override
    createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
    UrlTextField _urlTextField = UrlTextField();
    ...

    children:[
      _urlTextField,
      UsernameTextField(),
      UrlButton(_urlTextField)
    ]

Now we instantiated a UrlTextField which can be referenced to and can be passed to another widget like your UrlButton:

class UrlButton extends StatelessWidget {
    final UrlTextField urlTextField;

    UrlButton(this.urlTextField);

    @override
    Widget build(BuildContext context) {
        return AppButton(
            onPressed: () {
                String url = this.urlTextField.myController.text;
                String username = UsernameTextField().myController.text;
                print('url is $text');
            }
        );
    }
}

On this way you instantiated one UrlTextField and used it in your main page where a user can fill in some input and passed it down to UrlButton where you can access its controller and therefore its text.

I would recommend you to look more into the topic State Management since there are a lot of ways to handle such a case. I can recommend you to take a look on Provider which is very easy to use and convenient to access certain data.

Upvotes: 3

I think this what you are trying to do.... But there's many loop holes brother.. One thing to remember.. You need separate controllers for each TextField you can't declare one as myController and assign it to all. They'll all have the same value.

class StackHelp extends StatefulWidget {
  @override
  _StackHelp createState() => _StackHelp();
}

class _StackHelp extends State<StackHelp> {
  final TextEditingController myController = TextEditingController();

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: new Scaffold(
          body: Column(children: <Widget>[
        UrlTextField(myController),
        // UsernameTextField(),
        UrlButton(myController)
      ])),
    );
  }
}

class UrlTextField extends StatelessWidget {
  final TextEditingController myController;
  UrlTextField(this.myController);

  @override
  Widget build(BuildContext context) {
    return AppTextField(
      decoration:
          InputDecoration(prefixText: "https://", labelText: "Enter your URL"),
      myController: myController,
      textInputType: TextInputType.url,
    );
  }
}

class AppTextField extends StatelessWidget {
  final InputDecoration decoration;
  final TextEditingController myController;
  final TextInputType textInputType;
  AppTextField({this.decoration, this.myController, this.textInputType});

  @override
  Widget build(BuildContext context) {
    return TextFormField(
        controller: myController,
        keyboardType: textInputType,
        textAlign: TextAlign.left,
        decoration: decoration);
  }
}

class UrlButton extends StatelessWidget {
  final TextEditingController myController;
  UrlButton(this.myController);

  @override
  Widget build(BuildContext context) {
    void onPressed() {
      String url = this.myController.text;
      // String username = UsernameTextField().myController.text;
      print('url is $url');
    }

    return AppButton(onPressed);
  }
}

class AppButton extends StatelessWidget {
  final VoidCallback onPressed;
  AppButton(this.onPressed);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(child: Text('Test'), onPressed: onPressed);
  }
}

Upvotes: 0

Fethi
Fethi

Reputation: 927

what is the value of text in print('url is $text'); isn't it supposed to be like this print('url is $url');

Upvotes: 0

Related Questions