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);
}
}
I don't know if this will work but try this : in
SlotsTabbarBloc
bloc_selectAvailablePanelRadioButtonEvent
function at the end change this :to this :
also remove the
BlocProvider
form theAvailableOnClickWidget
and add it themain.dart
before theMaterialApp
something like this :