My code to show and submit login form:
class LoginWidget extends StatelessWidget {
const LoginWidget({
super.key,
});
@override
Widget build(BuildContext context) {
final citiesLoaded = context.select((LoginBloc bloc) => bloc.state.citiesLoaded);
final loginBloc = context.read<LoginBloc>();
final selectedCity = (citiesLoaded && loginBloc.state.cities.length == 1)
? loginBloc.state.cities[0]
: context.select((LoginBloc bloc) => bloc.state.selectedCity);
final formValidator = context.select((LoginBloc bloc) => bloc.state.formValidator);
final theme = Theme.of(context).extension<LoginPageThemeData>();
return AutofillGroup(
child: Column(
children: [
citiesLoaded
? Visibility(
visible: loginBloc.state.cities.length > 1,
child: CitySelectWidget(selectedCity: selectedCity),
)
: const BusyWidget(status: 'Loading cities'),
Text('Username:'),
TextFormField(
autofillHints: const [AutofillHints.username, AutofillHints.email, AutofillHints.name],
enabled: selectedCity != null,
initialValue: loginBloc.state.username,
keyboardType: TextInputType.emailAddress,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.usernameField.isValid ? null : formValidator.usernameField.validationMessage),
onChanged: (value) => loginBloc.add(SetUsernameEvent(username: value))),
Text('Password:'),
TextFormField(
autofillHints: const [AutofillHints.username, AutofillHints.email, AutofillHints.name],
enabled: selectedCity != null,
initialValue: loginBloc.state.password,
obscureText: true,
decoration: theme?.inputDecoration
?.copyWith(errorText: formValidator.passwordField.isValid ? null : formValidator.passwordField.validationMessage),
onChanged: (value) => loginBloc.add(SetPasswordEvent(password: value))),
ElevatedButton(
onPressed: selectedCity == null
? null
: () {
context.read<app_bloc.AppBloc>().add(app_bloc.SetSelectedCityEvent(selectedCity));
context.read<LoginBloc>().add(const AuthEvent());
},
child: Text('Sign in'),
),
],
),
);
}
}
In parent widget (login page) to show main app's page when aut process finished:
@override
Widget build(BuildContext context) {
return BlocListener<LoginBloc, LoginState>(
listenWhen: (previous, current) => previous.isLogged != current.isLogged || (current.loginFailed && !current.isBusy),
listener: (context, state) {
if (state.isLogged) {
Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
}
if (state.loginFailed) {
Fluttertoast.showToast(msg: state.statusMessage);
}
},
child: Scaffold( ......
So,on submit isLogged flag will be set on after auth success and app navigates to main main page + destroy login page. But autofill still does not work. No prompt to save password.
Any ideas what else I need to do?
There seems to be a few issues with the Autofill functionality, sometimes due to device type, operating system and system settings.
Troubleshoot Autofill while in development to come up with a best fit solution for many users.
But generally, to get the best of experience with it:
So you can have