I'm trying to learn bloc and I want to show an alertbox if the credentials are not valid. Im getting the state to the ui. But the alert box is not popping up.
The code is as follows.
bloc
class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
SignUpBloc() : super(SignUpInitialState()) {
on<OnClickedLoginEvent>((event, emit) => emit(LoginState()));
on<UserSignupEvent>(_signUp);
on<ValidateUserEvent>(_validateUserCred);
}
Future<SignUpState> _signUp(
UserSignupEvent event, Emitter<SignUpState> emit) async {
debugPrint("${event.email},${event.password}");
try {
add(ValidateUserEvent(event.email)); // added this event
//api calls
}
void _validateUserCred(ValidateUserEvent event, Emitter<SignUpState> emit) {
if (event.email.isEmpty) {
emit(UserCredNotValid("Email is empty"));
}
emit(UserCredValid("TESTing check valid"));
}
}
}
States
abstract class SignUpState extends Equatable {}
class UserCredNotValid extends SignUpState {
final String message;
UserCredNotValid(this.message);
@override
List<Object?> get props => [message];
}
class UserCredValid extends SignUpState{
final String message;
UserCredValid(this.message);
@override
List<Object?> get props => [message];
}
event
abstract class SignUpEvent extends Equatable {}
class ValidateUserEvent extends SignUpEvent{
final String email;
ValidateUserEvent(this.email);
@override
List<Object?> get props => [email];
}
on the ui i have used bloclistener
BlocListener(
bloc: BlocProvider.of<SignUpBloc>(context),
listener: (context, state) {
if (state is UserCredNotValid) {
debugPrint(state.message); // i'm getting the value here.
AlertDialog(
title: Text(state.message),
);
}
Is this the correct way to show an widget based on state? If not what is the better way using bloc?
Based on the code that i see I have created a example and made some changes as per your need.
Here I have used the following
Instead of bloc lisetner i have used the BlocConsumer which does the work of both listing and building so you don't need any other listner to listen. Check also the bloc implementation. State is being emited based on the email empty type. if not the sign up process will continue.
Main UI File
import 'package:flutter/material.dart';
import 'bloc/signup_state.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/signup_bloc.dart';
import 'bloc/signup_event.dart';
void main() {
runApp(MaterialApp(
home: BlocProvider(
create: (_) => SignUpBloc(),
child: const MyApp(),
),
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Signup App'),
),
body: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController emailcontroller = TextEditingController();
TextEditingController passwordcontroller = TextEditingController();
@override
Widget build(BuildContext context) {
return BlocConsumer(
bloc: BlocProvider.of<SignUpBloc>(context),
listener: (context, state) {
print(state);
if (state is UserCredNotValid) {
print('this is empty');
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text("Email is empty "),
content: const Text("Please add email for signup process"),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Container(
padding: const EdgeInsets.all(14),
child: const Text("okay"),
),
),
],
),
);
}
},
builder: (context, state) => Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextField(
controller: emailcontroller,
),
TextField(
controller: passwordcontroller,
),
ElevatedButton(
onPressed: () {
context
.read<SignUpBloc>()
.add(ValidateUserEvent(emailcontroller.text));
},
child: Text('SignUp'))
],
),
);
}
}
Bloc file
import 'dart:math';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/signup_event.dart';
import '../bloc/signup_state.dart';
class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
SignUpBloc() : super(SignUpInitialState()) {
// on<OnClickedLoginEvent>((event, emit) => emit(LoginState()));
// on<ValidateUserEvent>(_validateUserCred);
on<ValidateUserEvent>((event, emit) {
print(event.email.isEmpty);
if (event.email.isEmpty) {
emit(UserCredNotValid(event.email));
} else {
print(event.email);
// this is where you signup event will be executed.
add(UserSignupEvent());
}
});
on<UserSignupEvent>((event, emit) {
// this is where the signup api will be called.
});
}
///Not sure what you are doing nut i have commented it for now
// Future<SignUpState> _signUp(
// UserSignupEvent event, Emitter<SignUpState> emit) async {
// debugPrint("${event.email},${event.password}");
// try {
// add(ValidateUserEvent(event.email)); // added this event
// //api calls
// }
// void _validateUserCred(ValidateUserEvent event, Emitter<SignUpState> emit) {
// if (event.email.isEmpty) {
// emit(UserCredNotValid("Email is empty"));
// }
// emit(UserCredValid("TESTing check valid"));
// }
// }
}
Event File
import 'package:equatable/equatable.dart';
abstract class SignUpEvent extends Equatable {}
class ValidateUserEvent extends SignUpEvent {
final String email;
ValidateUserEvent(this.email);
@override
List<Object?> get props => [email];
}
class UserSignupEvent extends SignUpEvent {
@override
List<Object?> get props => [];
}
State File
import 'package:equatable/equatable.dart';
abstract class SignUpState {}
class UserCredNotValid extends SignUpState {
final String message;
UserCredNotValid(this.message);
}
class UserCredValid extends SignUpState with EquatableMixin {
final String message;
UserCredValid(this.message);
@override
List<Object?> get props => [message];
}
class SignUpInitialState extends SignUpState with EquatableMixin {
@override
List<Object?> get props => [];
}