I have created an event for radio button like functionality where user can select only single element at a time. But when I trigger the event to select the value, it does not update the state, however the list does get updated.
This is my bloc file
class SlotsTabbarBloc extends Bloc<SlotsTabbarEvent, SlotsTabbarState> {
SlotsTabbarSuccessState slotsTabbarSuccess =
SlotsTabbarSuccessState(slotData: const [], enableButton: true);
SlotsTabbarBloc(
this.slotsUsecase,
) : super(SlotsTabbarInitial()) {
SlotsTabbarLoading();
on<SelectAvailablePanelRadioButtonEvent>(
_selectAvailablePanelRadioButtonEvent,
);
}
Future<void> _selectAvailablePanelRadioButtonEvent(
SelectAvailablePanelRadioButtonEvent event,
Emitter<SlotsTabbarState> emit,
) async {
bool isAvailableSlotRadioEnabled = false;
for (int i = 0; i < event.dummyData.length; i++) {
event.dummyData[i].isSelected =
i == event.index ? isAvailableSlotRadioEnabled = true : false;
}
slotsTabbarSuccess = slotsTabbarSuccess.copyWith(
isAvailableSlotRadioEnabled: isAvailableSlotRadioEnabled,
availableSlotEntity: event.availableSlotEntity,
dummyData: event.dummyData,
);
emit(slotsTabbarSuccess);
}
}
This is the event class
class SelectAvailablePanelRadioButtonEvent extends SlotsTabbarEvent {
bool isAvailableSlotRadioEnabled;
final int index;
final AvailableSlotEntity availableSlotEntity;
final List<DummyData> dummyData;
final List<InterviewSlotDtoListEntity> slotData;
SelectAvailablePanelRadioButtonEvent({
required this.isAvailableSlotRadioEnabled,
required this.availableSlotEntity,
required this.index,
required this.dummyData,
required this.slotData,
});
}
this is the state class
class SlotsTabbarSuccessState extends SlotsTabbarState {
final List<InterviewSlotDtoListEntity> slotData;
final AvailableSlotEntity? availableSlotEntity;
final SpecificBookedCancelledSlotDetailsEntity?
specificBookedCancelledSlotDetailsEntity;
final String reasonForCancellationEnum;
final String cancellationReason;
final List<Map<String, dynamic>>? radioMap;
final bool enableButton;
final bool isRadioButtonSelected;
final bool isAvailableSlotRadioEnabled;
bool isBookedResponseTrue;
bool isCancelledResponseTrue;
bool markSlotAvailable;
final List<DummyData>? dummyData;
SlotsTabbarSuccessState({
this.dummyData,
required this.slotData,
this.specificBookedCancelledSlotDetailsEntity,
this.reasonForCancellationEnum = 'CANDIDATE_CANCEL',
this.availableSlotEntity,
this.radioMap,
// this.enableButton = true,
this.enableButton = true,
this.isAvailableSlotRadioEnabled = true,
this.isRadioButtonSelected = false,
this.isBookedResponseTrue = false,
this.isCancelledResponseTrue = false,
this.markSlotAvailable = false,
this.cancellationReason = '',
});
SlotsTabbarSuccessState copyWith({
final List<DummyData>? dummyData,
String? cancellationReason,
List<InterviewSlotDtoListEntity>? slotData,
AvailableSlotEntity? availableSlotEntity,
SpecificBookedCancelledSlotDetailsEntity?
specificBookedCancelledSlotDetailsEntity,
String? reasonForCancellationEnum = 'CANDIDATE_CANCEL',
List<Map<String, dynamic>>? radioMap,
bool? isBookedResponseTrue = false,
bool? isCancelledResponseTrue = false,
bool? markSlotAvailable = false,
bool? isRadioButtonSelected = false,
bool? isAvailableSlotRadioEnabled,
//bool? enableButton ,
bool? enableButton,
}) {
return SlotsTabbarSuccessState(
dummyData: dummyData ?? this.dummyData,
cancellationReason: cancellationReason ?? this.cancellationReason,
radioMap: radioMap ?? this.radioMap,
isAvailableSlotRadioEnabled:
isAvailableSlotRadioEnabled ?? this.isAvailableSlotRadioEnabled,
enableButton: enableButton ?? this.enableButton,
isRadioButtonSelected:
isRadioButtonSelected ?? this.isRadioButtonSelected,
markSlotAvailable: markSlotAvailable ?? this.markSlotAvailable,
reasonForCancellationEnum:
reasonForCancellationEnum ?? this.reasonForCancellationEnum,
slotData: slotData ?? this.slotData,
specificBookedCancelledSlotDetailsEntity:
specificBookedCancelledSlotDetailsEntity ??
this.specificBookedCancelledSlotDetailsEntity,
availableSlotEntity: availableSlotEntity ?? this.availableSlotEntity,
isBookedResponseTrue: isBookedResponseTrue ?? this.isBookedResponseTrue,
isCancelledResponseTrue:
isCancelledResponseTrue ?? this.isCancelledResponseTrue,
);
}
@override
List<Object> get props => [
slotData,
reasonForCancellationEnum,
isBookedResponseTrue,
isCancelledResponseTrue,
markSlotAvailable,
enableButton,
isAvailableSlotRadioEnabled,
isRadioButtonSelected,
cancellationReason,
];
}
here is how i am calling the bloc in the UI. Whenever I tap on the radio button, it should trigger the event, and the event should emit the state. The event gets triggered but the UI does not update on the screen. It updates after I refresh the screen.
import 'package:auto_route/auto_route.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DummyData {
final String name;
final String designation;
bool isSelected = false;
DummyData(
{required this.name,
required this.designation,
required this.isSelected});
}
class AvailableOnClickWidget extends StatelessWidget {
final String slotStartTime;
final String slotEndTime;
final bool showCheckBox;
final List<InterviewSlotDtoListEntity> slotData;
final String levelId;
final String techStackId;
bool isRadioButtonEnabled;
AvailableOnClickWidget({
super.key,
required this.slotData,
required this.slotStartTime,
required this.slotEndTime,
required this.showCheckBox,
required this.isRadioButtonEnabled,
required this.techStackId,
required this.levelId,
});
TextEditingController candidateNameContoller = TextEditingController();
// List<DummyData> dummyData = [
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// ];
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Injector.resolve<SlotsTabbarBloc>(),
child: BlocBuilder<SlotsTabbarBloc, SlotsTabbarState>(
builder: (context, state) {
if (state is SlotsTabbarInitial) {
BlocProvider.of<SlotsTabbarBloc>(context).add(
GetSpecificAvailableSlotDetailsEvent(
slotData: slotData,
fromTime: slotData[0].interviewSlotTimeDTOList[0].fromTime!,
toTime: slotData[0].interviewSlotTimeDTOList[0].toTime!,
slotDate: slotData[0].date!,
interviewLevelId: levelId,
techStackId: techStackId,
),
);
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is SlotsTabbarSuccessState) {
if (state.isBookedResponseTrue) {
CustomBotToastWidget.showToastWidget(
context: context,
onProgressBarCompletion: () {},
toastMessage: StringConstants.slotMarkedAsBooked,
showLinearProgressIndicator: false,
showToastActionButton: false,
cancelOnTap: () {
BotToast.cleanAll();
},
);
}
return SizedBox(
height: MediaQuery.of(context).size.height * 0.95,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
24.verticalSpace,
TitleWithCancelButtonWidget(
title:
'${state.availableSlotEntity!.slotDate}, $slotStartTime - $slotEndTime',
textStyle: TextStyleConstants.s14w600c101828fMontserrat,
),
40.verticalSpace,
Flexible(
fit: FlexFit.loose,
child: ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return AvailableOnClickPopUpListTile(
radioOnTap: () {
BlocProvider.of<SlotsTabbarBloc>(context).add(
SelectAvailablePanelRadioButtonEvent(
slotData: state.slotData,
availableSlotEntity:
state.availableSlotEntity!,
isAvailableSlotRadioEnabled:
state.dummyData![index].isSelected,
index: index,
dummyData: state.dummyData!,
),
);
},
imageUrl:
"https://lh3.googleusercontent.com/a/AEdFTp439zX_GEWqClFIwDVMbf8eUuCvqcLvjdiQcslZ=s96-c",
title: state.dummyData![index].name,
subtitle: state.dummyData![index].designation,
chipContainerText: state.dummyData![index].name,
isRadioButtonEnabled:
state.dummyData![index].isSelected
// ==
// state.isAvailableSlotRadioEnabled,
//,
);
// return AvailableOnClickPopUpListTile(
// imageUrl: state.availableSlotEntity!
// .slotUserDetailList[0].imageUrl,
// title:
// '${state.availableSlotEntity!.slotUserDetailList[0].firstName} ${state.availableSlotEntity!.slotUserDetailList[0].lastName}',
// subtitle: state.availableSlotEntity!
// .slotUserDetailList[0].designation,
// chipContainerText: state.availableSlotEntity!
// .slotUserDetailList[0].levelOfInterview,
// isRadioButtonEnabled:
// state.isAvailableSlotRadioEnabled,
// radioOnTap: () {
// BlocProvider.of<SlotsTabbarBloc>(context).add(
// SelectAvailablePanelRadioButtonEvent(
// availableSlotEntity: state.availableSlotEntity!,
// isAvailableSlotRadioEnabled: state
// .availableSlotEntity!
// .slotUserDetailList[0]
// .isSelected,
// ),
// );
// },
// );
},
separatorBuilder: (context, index) {
return 32.verticalSpace;
},
itemCount: state.dummyData!.length,
// state.availableSlotEntity!.slotUserDetailList.length,
),
),
40.verticalSpace,
ColumnWithHeadingTextFieldAndIsmFilledButton(
reasonForCancellationController: candidateNameContoller,
isAvailableOnClickWidget: true,
isCancelledOnClickWidget: false,
onPressed: () {
BlocProvider.of<SlotsTabbarBloc>(context).add(
MarkAsBookedEvent(
candidateName: candidateNameContoller.text,
interviewLevelId: levelId,
techStackId: techStackId,
slotId: state.availableSlotEntity!
.slotUserDetailList[0].slotId,
),
);
context.router.pop();
},
heading:
'${StringConstants.candidateName}${StringConstants.asterisk}',
maxLines: 1,
checkBoxOnChanged: (value) {},
textFieldOnChange: (value) {
BlocProvider.of<SlotsTabbarBloc>(context).add(
CandidateNameChangedEvent(
candidateName: candidateNameContoller.text,
enableButton: state.enableButton,
),
);
},
checkBoxBooleanValue: true,
ismFilledButtonText: StringConstants.markAsBooked,
isIsmButtonValid: state.enableButton,
showCheckBox: showCheckBox,
),
24.verticalSpace,
],
),
);
}
return const SizedBox.shrink();
},
),
).symmetricHorizontalPadding(16);
}
}
Thanks for the replies guys, it's a little late to post the answer but whta worked for me to emit the success state in this case was to remove the bloc state class and event class from extending to the Equatable
class.