Priyank Sharma
Priyank Sharma

Reputation: 159

Password show/hide toggle deletes password TextField value (Flutter)

When I click on show/hide toggle, both password and username textfield values gets deleted. I understand that, when setState rebuilds the widget tree, it resets password/username textfield values to initial blank values. I know I can get value of textfield, However I am not able to implement logic, how can I first get current username and password value, save it somewhere and then insert it back at the time widget rebuilds alongwith setState.

import 'package:flutter/material.dart';

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  bool _showPassword = true;

  @override
  Widget build(BuildContext context) {
    final usernameController = TextEditingController();
    final passwordController = TextEditingController();
    return SafeArea(
      child: Scaffold(
        body: Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Image(image: AssetImage('images/logo.png')),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: [
                    TextField(
                      controller: usernameController,
                      decoration: InputDecoration(
                        hintText: "Enter Username",
                        labelText: "UserName",
                      ),
                    ),
                    SizedBox(
                      height: 20.0,
                    ),
                    TextField(
                      obscureText: _showPassword,
                      controller: passwordController,
                      decoration: InputDecoration(
                        hintText: "Enter Password",
                        labelText: "Password",
                        suffixIcon: GestureDetector(
                          onTap: _togglePasswordVisibility,
                          child: _showPassword
                              ? Icon(Icons.visibility)
                              : Icon(Icons.visibility_off),
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 20.0,
                    ),
                    RaisedButton(
                      onPressed: () {
                        //call api here to authenticate user
                      },
                      child: Text("Login"),
                    ),
                  ],
                ),
              ),
              Column(
                children: [
                  Text("Don't have an account! Get it in 2 easy steps"),
                  RaisedButton(
                    onPressed: () {
                      //take user to registration screen
                    },
                    child: Text("Register"),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _togglePasswordVisibility() {
    setState(() {
      _showPassword = !_showPassword;
    });
  }
}

Upvotes: 1

Views: 2561

Answers (1)

Midhun MP
Midhun MP

Reputation: 107131

When you use the setState to toggle the visibility, the build method will get called to redraw that widget. Since you are initialising your TextEditingController in the build method, it get initialised again and loose the previous value. To fix this you just remove the initialisation from build method to class level.

class _LoginScreenState extends State<LoginScreen> {
  bool _showPassword = true;
  final usernameController = TextEditingController();
  final passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    
    return SafeArea(
        //... Your code
    );
  }
  //... Your code
}

Upvotes: 3

Related Questions