how can i confirm password using formz in flutter
Asked Answered
H

2

5

When I want to confirm my password, but i can not compare the first and last passwords.

Here my password class. It works fine, but confirmPassword section not.

class Password extends FormzInput<String, PasswordValidationError> {
  const Password.pure() : super.pure('');
  const Password.dirty([String value = '']) : super.dirty(value);

  static final _passwordRegExp = RegExp(r'^[A-Za-z\d@$!%*?&]{8,}$');

  @override
  PasswordValidationError? validator(String value) {
    if (value.isEmpty) {
      return PasswordValidationError.empty;
    }
    return _passwordRegExp.hasMatch(value)
        ? null
        : PasswordValidationError.invalid;
  }
}

You can ask what is the value in validator. Let me show you.

  void passwordChanged(String value) {
    final password = Password.dirty(value);
    emit(state.copyWith(
      password: password,
      status: Formz.validate(
          [state.name, state.email, password, state.confirmPassword]),
    ));
  }

This is my normal password field. Now let's look confirm section.

class ConfirmPassword
    extends FormzInput<String, ConfirmedPasswordValidationError> {
  const ConfirmPassword.pure() : super.pure('');
  const ConfirmPassword.dirty([String value = '']) : super.dirty(value);

  static final _confirmPasswordRegExp = RegExp(r'^[A-Za-z\d@$!%*?&]{8,}$');
  
  @override
  ConfirmedPasswordValidationError? validator(String value) {
    if (value.isEmpty) {
      return ConfirmedPasswordValidationError.empty;
    } else if (!_confirmPasswordRegExp.hasMatch(value)) {
      return ConfirmedPasswordValidationError.invalid;
    }
    return (password**I mentioned here** == value)
        ? null
        : ConfirmedPasswordValidationError.mismatch;
  }
}

and value in validator:

  void confirmPasswordChanged(String value) {
    final confirmPassword =
        ConfirmPassword.dirty(value);
    emit(state.copyWith(
      confirmPassword:
          state.password.valid ? confirmPassword : const ConfirmPassword.pure(),
      status: Formz.validate(
          [state.name, state.email, state.password, confirmPassword]),
    ));
  }

How can i reach the first (normal) value field in confirmPassword section? Or Is there any way to the use with formz?

Hairstreak answered 12/10, 2021 at 13:39 Comment(2)
Did you find any solution to this?Wiesbaden
no I did not...Hairstreak
S
16

This is a validator

 import 'package:formz/formz.dart';

enum ConfirmedPasswordValidationError {
  invalid,
  mismatch,
}

class ConfirmedPassword extends FormzInput<String, ConfirmedPasswordValidationError> {
  final String password;

  const ConfirmedPassword.pure({
    this.password = ''
  }) : super.pure('');

  const ConfirmedPassword.dirty({
    required this.password,
    String value = ''
  }) : super.dirty(value);

  @override
  ConfirmedPasswordValidationError? validator(String value) {
    if (value.isEmpty) {
      return ConfirmedPasswordValidationError.invalid;
    }
    return password == value
        ? null
        : ConfirmedPasswordValidationError.mismatch;
  }
}

extension Explanation on ConfirmedPasswordValidationError {
  String? get name {
    switch(this) {
      case ConfirmedPasswordValidationError.mismatch:
        return 'passwords must match';
      default:
        return null;
    }
  }
}

state management func bloc

  void _passwordConfirmationChanged(PasswordConfirmationChangede,Emitter<SignUpFormState> emit){
    final confirmedPassword = ConfirmedPassword.dirty(
      password: state.password.value,
      value: e.passwordConfirmStr,
    );
    emit(state.copyWith(
      confirmedPassword: confirmedPassword,
      status: Formz.validate([
        state.email,
        state.password,
        confirmedPassword,
      ]),
    ));
  }

Widget class

class _ConfirmPasswordInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SignUpFormBloc, SignUpFormState>(
      buildWhen: (previous, current) =>
          previous.password != current.password ||
          previous.confirmedPassword != current.confirmedPassword,
      builder: (context, state) {
        return TextField(
          key: const Key('signUpForm_confirmedPasswordInput_textField'),
          onChanged: (confirmPassword) => context.read<SignUpFormBloc>()
            .add(SignUpFormEvent.passwordConfirmationChanged(confirmPassword)),
          obscureText: true,
          decoration: InputDecoration(
            labelText: 'confirm password',
            helperText: '',
            errorText: state.confirmedPassword.invalid
                ? 'passwords do not match'
                : null,
          ),
        );
      },
    );
  }
}
Sexpot answered 27/12, 2021 at 16:19 Comment(3)
good job after a long time, it worksHairstreak
You have created "extension Explanation on ConfirmedPasswordValidationError ". Could you please elaborate on how instead of using static errorText in the widget like the one above, we can use the descriptions within extensions for various kinds of errors, in the widget text field itself?Novel
Every validator class have explanation extension on it. so you can pass message depend on type of validatorSexpot
I
2

Eng Mghase answer is correct

I have added the update of the confirmed password state on password update :

void _onPasswordChanged(
      SignupPasswordChanged event,
      Emitter<SignupState> emit,
    ) {
      final password = Password.dirty(event.password);
      final confirmPassword = ConfirmedPassword.dirty(password: password.value, value: state.confirmPassword.value);
      emit(state.copyWith(
        password: password,
        confirmPassword: confirmPassword,
        status: Formz.validate([password, confirmPassword, state.username]),
    ));
  }
Immensity answered 25/6, 2022 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.