ZoRa
ZoRa

Reputation: 389

how to validate a form field based on the value of the other?

I have 2 form fields,I want to validate the second form field to match the password from the first one,I tried but no success..thanks for answering.

Updated : I already have submit button and its working,I want Validator in the second field to validate the first field text to match the second field.

            new TextFormField(
          controller: _registerPassController,
          decoration: new InputDecoration(labelText: 'Password'),
          obscureText: true,
          validator: (value) =>
              value.isEmpty ? 'Password can\'t be empty' : null,
          onSaved: (value) => _password = value,
        ),
      ],
    ),
    new Stack(
      alignment: const Alignment(1.0, 1.0),
      children: <Widget>[
        new TextFormField(
          controller: _registerPassController2,
          decoration: new InputDecoration(labelText: 'Retype Password'),
          obscureText: true,
          validator: (value) {
            if (value.isEmpty) {
              return 'Please enter some text';
            }
          },),

Upvotes: 18

Views: 14552

Answers (6)

PixiiiDev
PixiiiDev

Reputation: 1

You can use a validator.

Define the validator:

class TwoFieldsMatchValidator extends TextFieldValidator {
  String checkField;
  TwoFieldsMatchValidator({required this.checkField, required String errorText}) : super(errorText);

  @override
  bool get ignoreEmptyValues => true;

  @override
  bool isValid(String? v) {
    return checkField == v;
  }
}

Use the validator:

final _controller = TextEditingController();
TextFormField(
    ...
    validator: MultiValidator(
    [
      TwoFieldsMatchValidator(
        checkField: _controller.text,
        errorText: "<Error>",
      ),
    ],
  ),
),

Hope this helps anyone in future.

Upvotes: 0

TSoftOne
TSoftOne

Reputation: 301

To have the operation done in the TextField's validator, we can use the onChanged event to capture the value of the password field and use it later in the validator of the confirm password field.

String _password;

Widget _passwordField() {
return new TextFormField(
    autocorrect: false,
    obscureText: true,
    decoration: InputDecoration(labelText: 'Password'),
    onChanged: (value) => _password = value,
    validator: (value) =>
      value.isEmpty ? "Password can't be empty" : null,
}

Widget _passwordConfirmField() {
    return new TextFormField(
        autocorrect: false,
        obscureText: true,
        decoration: InputDecoration(labelText: 'Retype Password'),
        validator: (value) =>
        value != _password ? "Passwords do not match!" : null,
    
}

final formKey = new GlobalKey<FormState>();
Widget _buildForm() {
    return new Form(
    autovalidate: true, 
    key: formKey, 
    child: new Column(children: <Widget>[
        _passwordField(),
        _passwordConfirmField(),
        new RaisedButton(
            child: Text('Sign Up'),
            onPressed: () => submit()
        )
     ]
 }

void submit() {
    final form = formKey.currentState;

    if (form.validate()) {
        form.save();  //this will cause the onSaved method to get called
    } 
}

Upvotes: 0

Chris
Chris

Reputation: 2034

This is my method, big thanks to Suhair. It is based on Suhair's but his didn't work for me...

(First Password)

TextFormField(
                    key: passKey,
                    obscureText: true,
                    decoration: InputDecoration(labelText: "Password"),
                    validator: (password) {
                      var result = password.length < 4
                          ? "Password should have at least 4 characters"
                          : null;
                      return result;
                    },
                  ),

(Second)

TextFormField(
                    obscureText: true,
                    decoration: InputDecoration(labelText: "Confirm Password"),
                    validator: (confirmation) {
                      if (confirmation != passKey.currentState.value) {
                        return 'Passwords do not match';
                      } else {
                        return null;
                      }
                    },
                  ),

and you also need to declare you variable

 var passKey = GlobalKey<FormFieldState>();

Upvotes: 0

ZoRa
ZoRa

Reputation: 389

I finally find the answer,its so simple actually.

        new TextFormField(
          controller: _registerPassController2,
          decoration: new InputDecoration(labelText: 'Retype Password'),
          obscureText: true,
          validator: (value) {
            if (value != _registerPassController.text) {
              return 'Password is not matching';
            }
          },
        ),

Upvotes: 20

suhair
suhair

Reputation: 10929

Since you are using formfield it will be appropriate to use the key to access the value of other field. You can declare the global key like this

var passKey = GlobalKey<FormFieldState>();

Then pass it to the password field to retrieve its value during validation.

TextFormField(
  key: passKey,
  obscureText: true,
  decoration: InputDecoration(
      labelText: "Password"
  ),
  validator: (password){
    var result = password.length < 4 ? "Password should have at least 4 characters" : null;
    return result;
  },
);

Then you can use the password inside the confirmation validator like this

TextFormField(
  obscureText: true,
  decoration: InputDecoration(
      labelText: "Confirm Password"
  ),
  validator: (confirmation){
    var password = passKey.currentState.value;
    return equals(confirmation, password) ? null : "Confirm Password should match password";
  },
);

Upvotes: 19

aqwert
aqwert

Reputation: 10789

The way I do this is to validate on a submit button and then show a message.

  String _password;
  Widget _passwordField() {
    return new TextFormField(
        autocorrect: false,
        obscureText: true,
        decoration: InputDecoration(labelText: 'Password'),
        validator: (value) =>
          value.isEmpty ? "Password can't be empty" : null,
        onSaved: (val) => _password = val;
  }

  String _passwordConfirm;
  Widget _passwordConfirmField() {
    return new TextFormField(
        autocorrect: false,
        obscureText: true,
        decoration: InputDecoration(labelText: 'Retype Password'),
        validator: (value) =>
          value.isEmpty ? "Password can't be empty" : null,
        onSaved: (val) => _passwordConfirm = val;
  }

  final formKey = new GlobalKey<FormState>();
  Widget _buildForm() {
     return new Form(
      autovalidate: true, 
      key: formKey, 
      child: new Column(children: <Widget>[
         _passwordField(),
         _passwordConfirmField(),
         new RaisedButton(
            child: Text('Sign Up'),
            onPressed: () => submit()
         )
      ]

  }

void submit() {
   final form = formKey.currentState;

   if (form.validate()) {
      form.save();  //this will cause the onSaved method to get called

      //you will need to do some additional validation here like matching passwords
      if(_password != _passwordConfirm) {
         showDialog(....)
      } else {
         //complete
      }
   } 

}

Note: This is a StatefulWidget

Upvotes: 0

Related Questions