I have 2 textFields that have a gesture detector and on tap of the gesture detector, I open an AlertDialog using the BlocListener widget.
Widget _getSourceAndOriginTextField(String hintText, controller) {
final portsCubit = BlocProvider.of<PortsCubit>(context);
return TextFormField(
controller: controller..text = "",
readOnly: true,
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
portsCubit.getAllPorts();
},
child: BlocListener<PortsCubit, PortsState>(
listenWhen: (previous, current) => previous != current,
listener: (context, state) async {
if (state is PortsLoadedState) {
await showDialog(
context: context,
builder: (_) => BlocProvider.value(
value: portsCubit,
child: PortsDialog(state.portsList),
));
}
},
child: SvgPicture.asset(
'assets/svg/chevron_down_icon.svg',
fit: BoxFit.scaleDown,
height: 10,
width: 18,
),
)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color: Colors.transparent,
style: BorderStyle.solid,
width: 1,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
contentPadding: EdgeInsets.all(8),
hintText: hintText,
hintStyle: AppStyle.hintStyle),
);
}
This method above which returns a TextField is being used inside the form to display two textfields.
Form(
children:[_getSourceAndOriginTextField('Origin',controller),
SizedBox(height:10),
_getSourceAndOriginTextField('Origin',controller)])
When I tap on one of the textfields the state changes and the dialog opens but the dialog is displayed twice. What am I missing here?
Following are the images for reference, any help will be appreciated.
CodePudding user response:
I have 2 textFields
and
This method above which returns a TextField is being used inside the form to display two textfields.
basically explains your problem. Since you are executing _getSourceAndOriginTextField()
twice, you also create the BlocListener<PortsCubit, PortsState>(...)
twice. Thus, when the PortsCubit
state changes to PortsLoadedState
, both listeners trigger the showDialog
function.
What you can do is lift the BlocListener
and wrap the Form
with it. This way you will have only a single listener that could open the dialog:
BlocListener<PortsCubit, PortsState>(
listenWhen: (previous, current) => previous != current,
listener: (context, state) async {
if (state is PortsLoadedState) {
await showDialog(
context: context,
builder: (_) => BlocProvider.value(
value: portsCubit,
child: PortsDialog(state.portsList),
));
},
child: Form(
children:[_getSourceAndOriginTextField('Origin',controller),
SizedBox(height:10),
_getSourceAndOriginTextField('Origin',controller)])
},