15

I do question regarding Dart and Flutter. So I'm trying to refactor some code and I'm stuck in a referencing problem.

class _LoginPageState extends State<LoginPage> {
  String _email;
  String _password;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: new AppBar(
          title: new Text("Login Page"),
        ),
        body: new Container(
          padding: new EdgeInsets.all(16),
          child: new Form(
              child: new Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: buildInputs()
              )),
        ));
  }

  Widget buildInput(String label, String val) {
    return new TextFormField(
      decoration: new InputDecoration(
        labelText: label,
      ),
      validator: (value) => value.isEmpty ? "$label can't be empty" : null,
      onSaved: (value) => val = value,
    );
  }

  List<Widget> buildInputs() {
    return [
      buildInput("Email", this._email),
      buildInput("Password", this._password),
    ];
  }
}

I'm trying to create a function called buildInput which will take 2 parameters, one will be my label from my form and the second one will be the actual variable which I want to modify. Now here is the tricky part, for some reason I have no idea why... but my variable is never going to set with the correct value, and it is always null.

Any idea how can I pass a parameter with a function in order to modified in the body of the function and the parameter to stay medicated and after the function call is done?

Amit Jangid
  • 2,741
  • 1
  • 22
  • 28
Vali
  • 629
  • 2
  • 6
  • 14

1 Answers1

6

Since you are using the _email and _password variables in the same class, why use an extra parameter? You can just do something like:

  Widget buildInput(String label) {
    return new TextFormField(
      decoration: new InputDecoration(
        labelText: label,
      ),
      validator: (value) => value.isEmpty ? "$label can't be empty" : null,
      onSaved: (value) => this._email = value,
    );
  }

Also, the dart language does not support passing primitives by reference so they will be always passed by value. If at all you need to pass by reference then you will need to wrap the _email and _password variables inside a separate model class and pass an object of that class to the buildInputs() function.

You can refer to this question for more details on passing by reference in Dart. Hope this helps!

UPDATE:

If you need to use only a single function for the TextField then there is a workaround. You can do something like this:

  Widget buildInput(String label, String val) {
    return new TextFormField(
      decoration: new InputDecoration(
        labelText: label,
      ),
      validator: (value) => value.isEmpty ? "$label can't be empty" : null,
      onSaved: (value) {
        if(val == "email")
          this._email = value;
        else if(val == "password")
          this._password = value;
      }
    );
  }

And you can call the function like this:

  List<Widget> buildInputs() {
    return [
      buildInput("Email", "email"),
      buildInput("Password", "password"),
    ];
  }

This is just one way to check if the data is an email or a password. You can also achieve the same with a bool variable or using enum.

bytesizedwizard
  • 5,529
  • 3
  • 17
  • 39
  • But this is exactly what I don't want to do, this is exactly the opposite of what I want to do. My idea was to have ONE function, not to use TWO with duplicate pieces of code that are doing the exact same thing with the only diff been the actually variable. – Vali Mar 14 '19 at 09:37
  • There might be a small workaround for the thing that you need. You can use the `val` argument to check if the text is an email or a password. I'll update my answer with another example. – bytesizedwizard Mar 14 '19 at 09:42
  • You cannot pass a variable by reference. There needs to be separate assignments to `_email` and `_password` in your code, because each assignment can only assign to one of them. You can then fiddle with how to choose which assignment to use, but there needs to be two separate assignments somewhere. You can also use pass a single function as the argument, `(String value) { this._email = value; }` or `(String value) { this._password = value; }`, and then call the passed function in `onSave` (or use it directly as the value for the `onSave` parameter). – lrn Mar 14 '19 at 10:37
  • `this` keyword is undefined.. So, I used `class_name().variable_name`. Is it best practice? – BIS Tech Sep 26 '19 at 19:28