Hi,
I have a screen that user must write his mobile number on the input.
I use bloc in this screen.
Base on initial state everything work.
but when an event called nothing change.
here is my bloc:
class MobileVerifyBloc extends Bloc<MobileVerifyEvent, MobileVerifyState> {
final MobileVerifyRepository mobileVerifyRepository;
MobileVerifyBloc({this.mobileVerifyRepository}) : assert(mobileVerifyRepository != null);
@override
MobileVerifyState get initialState => MobileVerifyInitial();
@override
Stream<MobileVerifyState> mapEventToState(MobileVerifyEvent event) async* {
print('come here');
if (event is MobileVerifyInputChanged) {
print(event.mobile);
mobileVerifyRepository.setMobile(event.mobile);
yield MobileVerifyMobile(mobile: event.mobile);
}
if (event is MobileVerifyButtonPressed) {
print('come here2');
yield MobileVerifyLoading();
try {
// TODO Call API
yield MobileVerifyInitial();
} catch (error) {
yield MobileVerifyFailure(error: error.toString());
}
}
}
}
and event:
abstract class MobileVerifyEvent extends Equatable {
const MobileVerifyEvent();
}
class MobileVerifyButtonPressed extends MobileVerifyEvent {
final String mobile;
const MobileVerifyButtonPressed({
@required this.mobile,
});
@override
List<Object> get props => [mobile];
@override
String toString() => 'MobileVerifyButtonPressed { mobile: $mobile }';
}
class MobileVerifyInputChanged extends MobileVerifyEvent {
final String mobile;
const MobileVerifyInputChanged({
@required this.mobile,
});
@override
List<Object> get props => [mobile];
@override
String toString() => 'MobileVerifyButtonPressed { mobile: $mobile }';
}
and state:
abstract class MobileVerifyState extends Equatable {
const MobileVerifyState();
@override
List<Object> get props => [];
}
// bloc initialize
class MobileVerifyInitial extends MobileVerifyState {}
class MobileVerifyValidateSuccessfull extends MobileVerifyState {}
class MobileVerifyMobile extends MobileVerifyState {
final String mobile;
const MobileVerifyMobile({@required this.mobile});
@override
List<Object> get props => [mobile];
@override
String toString() => 'MobileVerifyError { error $mobile }';
}
// Mobile validation failed
class MobileVerifyError extends MobileVerifyState {
final String error;
const MobileVerifyError({@required this.error});
@override
List<Object> get props => [error];
@override
String toString() => 'MobileVerifyError { error $error }';
}
// API is called
class MobileVerifyLoading extends MobileVerifyState {}
// API called failed
class MobileVerifyFailure extends MobileVerifyState {
final String error;
const MobileVerifyFailure({@required this.error});
@override
List<Object> get props => [error];
@override
String toString() => 'MobileVerifyFailure { error: $error }';
}
// API is OK
class MobileVerifySuccessful extends MobileVerifyState {}
this is my repository:
class MobileVerifyRepository {
String mobile;
void setMobile(mobile) {
this.mobile = mobile;
}
}
and my UI where I use bloc:
class MobileVeifyScreen extends StatelessWidget {
final _formKey = GlobalKey<FormState>();
final bool _autoValidate = false;
final _mobileController = TextEditingController();
final MobileVerifyRepository mobileVerifyRepository = MobileVerifyRepository();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ColorPalette.verifyMobileBC,
body: Builder(
builder: (context) {
return BlocProvider(
create: (context) {
return MobileVerifyBloc(mobileVerifyRepository: mobileVerifyRepository);
},
child: BlocListener<MobileVerifyBloc, MobileVerifyState>(
listener: (context, state) {
if (state is MobileVerifyFailure) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.error}'),
backgroundColor: Colors.red,
),
);
}
},
child: BlocBuilder<MobileVerifyBloc, MobileVerifyState>(
builder: (context, state) => Scroll(
child: AuthCard(
image: Assets.mobileVerify,
title: Strings.mobileVerifyTitle,
render: Column(
children: <Widget>[
Form(
autovalidate: _autoValidate,
key: _formKey,
child: Container(
width: 300.0,
child: Input(
controller: _mobileController,
textAlign: TextAlign.left,
inErr: state is MobileVerifyError,
hintText: Strings.mobileHint,
onChanged: (value) => MobileVerifyInputChanged(mobile: value),
keyboardType: 'number',
maxLength: 11,
prefixIcon: Icons.done,
prefixIconColor: (state is MobileVerifyValidateSuccessfull) ? Colors.green : Colors.grey,
isSuccess: (state is MobileVerifyValidateSuccessfull) ? true : false,
),
),
),
RaisedButton(
onPressed: () => MobileVerifyButtonPressed(mobile: _mobileController.text),
child: Text('click'),
)
],
),
),
),
),
),
);
},
),
);
}
}
It seem my mapEventToState not called at all.
What's my problem?
You are using this package wrong. You have to call myBloc.add(myEvent) method, not only return event, which will do, of course, nothing.
E.g. instead of
RaisedButton(
onPressed: () => MobileVerifyButtonPressed(mobile: _mobileController.text),
child: Text('click'),
)
you should do
RaisedButton(
onPressed: () => BlocProvider.of<MobileVerifyBloc>(context).add(MobileVerifyButtonPressed(mobile: _mobileController.text)),
child: Text('click'),
)
For more information, see https://bloclibrary.dev/#/flutterbloccoreconcepts
@tenhobi
yes, tnx for reply and help.
Most helpful comment
You are using this package wrong. You have to call
myBloc.add(myEvent)method, not only return event, which will do, of course, nothing.E.g. instead of
you should do
For more information, see https://bloclibrary.dev/#/flutterbloccoreconcepts