skip to Main Content

In the following code, I’m trying to make a login screen. However, even after I type email and password, I get a popup telling me "Email or password is empty", which is expected inside my if check.

login_page.dart

import 'package:chat_app/auth/auth_service.dart';
import 'package:chat_app/components/custom_button.dart';
import 'package:chat_app/components/custom_textfield.dart';
import 'package:flutter/material.dart';

class LoginPage extends StatelessWidget {
  final void Function()? onTap;

  LoginPage({super.key, required this.onTap});

  final TextEditingController _emailController = TextEditingController();

  final TextEditingController _passwordController = TextEditingController();

  void login(BuildContext context) async {
    final authService = AuthService();
    final localContext = context;

    String email = _emailController.text.trim();
    String password = _passwordController.text.trim();

    if (email.isEmpty || password.isEmpty) {
      showDialog(
        context: localContext,
        builder: (context) => AlertDialog(
          title: const Text("Error"),
          content: const Text("Email or password is empty"),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(localContext),
              child: const Text("Ok"),
            )
          ],
        ),
      );
      return; // Exit the method if email or password is empty
    }

    try {
      await authService.signInWithEmailAndPassword(
          _emailController.text.trim(), _passwordController.text.trim());
    } catch (e) {
      showDialog(
        context: localContext,
        builder: (localContext) => AlertDialog(
          title: const Text("Error"),
          content: Text(e.toString()),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(localContext),
              child: const Text("Ok"),
            )
          ],
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            Icons.message_rounded,
            size: 60,
            color: Theme.of(context).colorScheme.primary,
          ),
          const SizedBox(height: 60),
          Text(
            "Welcome back, you've been missed",
            style: TextStyle(
              color: Theme.of(context).colorScheme.primary,
              fontSize: 16,
            ),
          ),
          const SizedBox(height: 20),
          CustomTextField(
            hintText: "[email protected]",
            obscureText: false,
            controller: _emailController,
          ),
          const SizedBox(height: 25),
          CustomTextField(
            hintText: "Password",
            obscureText: true,
            controller: _passwordController,
          ),
          const SizedBox(height: 25),
          CustomButton(text: "Login", onTap: () => login(context)),
          const SizedBox(height: 25),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                "Not a member? ",
                style: TextStyle(color: Theme.of(context).colorScheme.primary),
              ),
              GestureDetector(
                onTap: onTap,
                child: Text(
                  "Register now",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Theme.of(context).colorScheme.primary,
                  ),
                ),
              )
            ],
          )
        ],
      ),
    );
  }
}

custom_textfield.dart

import 'package:flutter/material.dart';

class CustomTextField extends StatelessWidget {
  final String hintText;
  final bool obscureText;
  final TextEditingController controller = TextEditingController();

  CustomTextField({super.key, required controller, required this.hintText, required this.obscureText});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 25.0),
      child: TextField(
        obscureText: obscureText,
        controller: controller,
        decoration: InputDecoration(
          enabledBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Theme.of(context).colorScheme.tertiary,
            ),
            borderRadius: BorderRadius.circular(10),
          ),
          focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(
              color: Theme.of(context).colorScheme.primary,
            ),
            borderRadius: BorderRadius.circular(10),
          ),
          fillColor: Theme.of(context).colorScheme.secondary,
          filled: true,
          hintText: hintText,
          hintStyle: TextStyle(
            color: Theme.of(context).colorScheme.primary,
          ),
        ),
      ),
    );
  }
}

I just can’t understand how the controllers are appearing as an empty string like "", as if they aren’t receiving values at all. Any sugestions?

2

Answers


  1. Just change the onTap
    Instead of this

    GestureDetector(
                    onTap: onTap,
                    child: Text(
                      "Register now",
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        color: Theme.of(context).colorScheme.primary,
                      ),
                    ),
                  )
    

    To This

    GestureDetector(
                        onTap: ()=>onTap(),
                        child: Text(
                          "Register now",
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            color: Theme.of(context).colorScheme.primary,
                          ),
                        ),
                      )
    
    Login or Signup to reply.
  2. In CustomTextField, you have a controller field that is initialized with a TextEditingController(), while the controller parameter from the constructor is not used. It makes CustomTextField uses its own TextEditingController instead of using the one passed from the parent widget. Fix it by applying these two changes:

    class CustomTextField extends StatelessWidget {
      final String hintText;
      final bool obscureText;
      final TextEditingController controller; // (1) Remove the assignment
    
      // (2) Change `required controller` to `required this.controller`
      CustomTextField({super.key, required this.controller, required this.hintText, required this.obscureText});
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search