I am working on one project with BLoC.I have made some classes to update the data.
Data will come once you pass the placeID.
But once you pass the PlaceID first time it will give the data and widgets updated.
But once I pass new placeID old data not being updated. It shows old data.
All Code Files:
RestaurantDetailBloc.dart
class RestaurantDetailBloc extends Bloc<RestaurantDetailEvent, RestaurantDetailState> {
static final RestaurantDetailBloc _restaurantDetailBlocSingleton = new RestaurantDetailBloc._internal();
factory RestaurantDetailBloc() {
return _restaurantDetailBlocSingleton;
}
RestaurantDetailBloc._internal();
RestaurantDetailState get initialState => new UnRestaurantDetailState();
#override
Stream<RestaurantDetailState> mapEventToState(
RestaurantDetailEvent event,
) async* {
try {
yield await event.applyAsync(currentState: currentState, bloc: this);
} catch (_, stackTrace) {
print('$_ $stackTrace');
yield currentState;
}
}
}
LoadRestaurantDetailEvent.dart
#immutable
abstract class RestaurantDetailEvent {
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc});
final RestaurantDetailProvider _provider = RestaurantDetailProvider();
}
class LoadRestaurantDetailEvent extends RestaurantDetailEvent {
#override
String toString() => 'LoadRestaurantDetailEvent';
String placeID;
LoadRestaurantDetailEvent({Key key,this.placeID});
#override
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc}) async {
try {
await Future.delayed(new Duration(seconds: 2));
var component = await _provider.getRestaurantReview(placeID);
print(component);
return new InRestaurantDetailState(component);
} catch (_, stackTrace) {
print('$_ $stackTrace');
return new ErrorRestaurantDetailState(_?.toString());
}
}
}
RestaurantDetailPage.dart
class RestaurantDetailPage extends StatelessWidget {
static const String routeName = "/restaurantDetail";
final String imageURL;
final String placeID;
const RestaurantDetailPage({Key key, this.imageURL,this.placeID}) : super(key: key);
#override
Widget build(BuildContext context) {
var _restaurantDetailBloc = new RestaurantDetailBloc();
return new RestaurantDetailScreen(restaurantDetailBloc: _restaurantDetailBloc,imageUrl: this.imageURL,placeId: this.placeID,);
}
}
RestaurantDetailProvider.dart
class RestaurantDetailProvider {
String getBaseUrl(String placeID){
final urlBase = "https://maps.googleapis.com/maps/api/place/details/json?placeid=$placeID&key=xxxxxxxxxxxxxGooglePlaceKey";
return urlBase;
}
Future<void> loadAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<void> saveAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<Map<String, dynamic>> getRestaurantReview(String placeId)async{
var response = await http.get(getBaseUrl(placeId));
RestaurantReviews reviews = RestaurantReviews();
if(response.statusCode == 200){
var decodedJson = jsonDecode(response.body);
print(decodedJson);
//reviews.result = decodedJson['result'];
return decodedJson;
}
else{
}
}
}
InRestaurantDetailState.dart
#immutable
abstract class RestaurantDetailState extends Equatable {
RestaurantDetailState([Iterable props]) : super(props);
/// Copy object for use in action
RestaurantDetailState getStateCopy();
}
/// UnInitialized
class UnRestaurantDetailState extends RestaurantDetailState {
#override
String toString() => 'UnRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return UnRestaurantDetailState();
}
}
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
InRestaurantDetailState(this.resReview);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}
class ErrorRestaurantDetailState extends RestaurantDetailState {
final String errorMessage;
ErrorRestaurantDetailState(this.errorMessage);
#override
String toString() => 'ErrorRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return ErrorRestaurantDetailState(this.errorMessage);
}
}
RestaurantDetailScreenState.dart
class RestaurantDetailScreen extends StatefulWidget {
const RestaurantDetailScreen({
Key key,
#required RestaurantDetailBloc restaurantDetailBloc,
this.imageUrl, this.placeId,
}) : _restaurantDetailBloc = restaurantDetailBloc,
super(key: key);
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
#override
RestaurantDetailScreenState createState() {
return new RestaurantDetailScreenState(_restaurantDetailBloc, imageUrl,placeId);
}
}
class RestaurantDetailScreenState extends State<RestaurantDetailScreen> {
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
RestaurantDetailScreenState(this._restaurantDetailBloc, this.imageUrl,this.placeId);
#override
void initState() {
super.initState();
this._restaurantDetailBloc.dispatch(LoadRestaurantDetailEvent(placeID:placeId));
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
return BlocBuilder<RestaurantDetailBloc, RestaurantDetailState>(
bloc: widget._restaurantDetailBloc,
builder: (
BuildContext context,
var currentState,
) {
if (currentState is UnRestaurantDetailState) {
return MaterialApp(
home: new Scaffold(
body: new Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
if (currentState is ErrorRestaurantDetailState) {
return new Container(
child: new Center(
child: new Text(currentState.errorMessage ?? 'Error'),
));
}
if (currentState is InRestaurantDetailState) {
var resList = currentState.resReview;
print(resList);
return MaterialApp(
home: new Scaffold(
)
);
}
Please help me guys.I have spent whole day.
Thank you in advance.
You need to pass the data to the parent class for comparison. That's why we are using equatable. Do these changes and it should work. Let me know if it doesn’t.
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
//You need to change this line to
InRestaurantDetailState(this.resReview):super([resReview]);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}
Related
Im am trying to get userData by id to show userProfile. I create a cubitProfile for this reason but when I go to the profile page the app ProviderNotFoundException(T, context.widget.runtimeType) apears. Can u help me with this error?
Here is my code:
profile
class ProfileScreen extends StatelessWidget {
final String id;
const ProfileScreen({Key? key, required this.id}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocBuilder<ProfileCubit, ProfileStates>(builder: (context, state) {
var cubit = ProfileCubit.get(context);
return Scaffold(
...
profileCubit
class ProfileCubit extends Cubit<ProfileStates> {
ProfileCubit() : super(ProfileInitState());
static ProfileCubit get(context) => BlocProvider.of(context);
late UserData userData;
void getUserDataById(String id) {
emit(ProfileGetUserLoadingState());
FirebaseFirestore.instance.collection('users').doc(id).get().then((value) {
userData = UserData.fromJson(jsonDecode(jsonEncode(value.data())));
emit(ProfileGetUserSuccessState());
}).catchError((error) {
print(error);
emit(ProfileGetUserErrorState());
});
}
bool isSameUser(String uid) {
if (FirebaseAuth.instance.currentUser!.uid != uid) {
return false;
} else {
return true;
}
}
}
I'm currently learning and converting my code to BLoc pattern. Before I'm using flutter_pagewise ^1.2.3 for my infinite scroll using Future<> but I don't know how to use it using bloc or is it compatible with it.
So now I'm trying infinite_scroll_pagination: ^2.3.0 since it says in its docs that it supports Bloc. But I don't understand the example code in the docs for bloc. Can you give me a simple example of how to use it with bloc? I'm currently using flutter_bloc: ^6.1.3.
Here are my bloc script:
class TimeslotViewBloc extends Bloc<TimeslotViewEvent, TimeslotViewState> {
final GetTimeslotView gettimeslotView;
TimeslotViewBloc({this.gettimeslotView}) : super(TimeslotViewInitialState());
#override
Stream<TimeslotViewState> mapEventToState(
TimeslotViewEvent event,
) async* {
if (event is GetTimeslotViewEvent) {
yield TimeslotViewLoadingState();
final failureOrSuccess = await gettimeslotView(Params(
id: event.id,
date: event.date,
));
yield* _eitherLoadedOrErrorState(failureOrSuccess);
}
}
Stream<TimeslotViewState> _eitherLoadedOrErrorState(
Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
) async* {
yield failureOrTrivia.fold(
(failure) => TimeslotViewErrorState(
message: _mapFailureToMessage(failure), failure: failure),
(result) => TimeslotViewLoadedState(result),
);
}
//Bloc Events----------------------------------------
abstract class TimeslotViewEvent extends Equatable {
const TimeslotViewEvent();
#override
List<Object> get props => [];
}
class GetTimeslotViewEvent extends TimeslotViewEvent {
final String id;
final String date;
final int offset;
final int limit;
GetTimeslotViewEvent(
{this.id,
this.date,
this.offset,
this.limit});
}
//Bloc States----------------------------------------
abstract class TimeslotViewState extends Equatable {
const TimeslotViewState();
#override
List<Object> get props => [];
}
class TimeslotViewLoadingState extends TimeslotViewState {}
class TimeslotViewLoadedState extends TimeslotViewState {
final List<TimeslotViewEntity> records;
TimeslotViewLoadedState(this.records);
#override
List<Object> get props => [records];
}
UPDATE: Here is the revised code from Davii that works for me
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _timeLotBloc,
child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
listener: (context, state) {
if (state is TimeslotViewLoadedState) {
//Save record count instead of records list
totalRecordCount += state.records.length;
final _next = 1 + totalRecordCount;
final isLastPage = state.records.length < PAGE_SIZE;
if (isLastPage) {
_pagingController.appendLastPage(state.records);
} else {
_pagingController.appendPage(state.records, _next);
}
}
if (state is TimeslotViewErrorState) {
_pagingController.error = state.error;
}
},
//Removed pagedListview from bloc builder
child: PagedListView<int, TimeslotViewEntity>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
character: time,
),
),
),),
);
}
class PaginatedList extends StatefulWidget {
const PaginatedList({Key? key}) : super(key: key);
#override
_PaginatedListState createState() => _PaginatedListState();
}
class _PaginatedListState extends State<PaginatedList> {
//*bloc assuming you use getIt and injectable
late final _timeLotBloc = getIt<TimeslotViewBloc>();
List<TimeslotViewEntity> records = [];
//*initialize page controller
final PagingController<int, TimeslotViewEntity> _pagingController =
PagingController(firstPageKey: 0);
#override
void initState() {
super.initState();
//*so at event add list of records
_pagingController.addPageRequestListener(
(pageKey) => _timeLotBloc
.add(GetTimeslotViewEvent(records: records, offset: pageKey,limit: 10)),
);
}
#override
void dispose() {
super.dispose();
_timeLotBloc.close();
_pagingController.dispose();
}
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _timeLotBloc,
child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
listener: (context, state) {
if (state is TimeslotViewLoadedState) {
records =state.records;
//forget about existing record
//about the last page, fetch last page number from
//backend
int lastPage = state.lastPage
final _next = 1 + records.length;
if(_next>lastPage){
_pagingController.appendLastPage(records);
}
else{
_pagingController.appendPage(records, _next);
}
}
if (state is TimeslotViewErrorState) {
_pagingController.error = state.error;
}
},child: BlocBuilder<TimeslotViewBloc,TimeslotViewState>(
builder: (context,state)=> PagedListView<int, TimeslotViewEntity>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
character: time,
),
),
),),
),
);
}
}
now on the bloc event class
class GetTimeslotViewEvent extends TimeslotViewEvent {
final String id;
final String date;
final int offset;
final int limit;
//add this on event
final List<TimeslotViewEntity> records;
GetTimeslotViewEvent({
this.id,
this.date,
this.offset,
this.limit,
required this.records,
});
}
on state class
class TimeslotViewLoadedState extends TimeslotViewState {
final List<TimeslotViewEntity> records;
final List<TimeslotViewEntity> existingRecords;
TimeslotViewLoadedState(this.records, this.existingRecords);
#override
List<Object> get props => [records, existingRecords];
}
and on bloc now
yield* _eitherLoadedOrErrorState(failureOrSuccess,event);
Stream<TimeslotViewState> _eitherLoadedOrErrorState(
Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
GetTimeslotViewEvent event,
) async* {
yield failureOrTrivia.fold(
(failure) => TimeslotViewErrorState(
message: _mapFailureToMessage(failure), failure: failure),
//existing records from the event,
(result) => TimeslotViewLoadedState(result,event.records),
);
}
yap this method worked on me
I update state bloc builder context like this context.read<SurveyBloc>().add(SurveyModeChanged(mode: 'draft')); in the bloc file state changing is triggered but value always null. the last 2days I struck with this someone please help to resolve this issue.
if (event is SurveyModeChanged) {
print('mode==>');
print(state.mode);
yield state.copyWith(mode: state.mode);
}
This is Survey screen file
class SurveyView extends StatefulWidget {
#override
State<StatefulWidget> createState() => _SurveyViewState();
}
class _SurveyViewState extends State<SurveyView> {
#override
Widget build(BuildContext context) {
final sessionCubit = context.read<SessionCubit>();
return BlocProvider(
create: (context) => SurveyBloc(
user: sessionCubit.selectedUser ?? sessionCubit.currentUser,
surveyId: '4aa842ff-2b7d-4364-9669-29c200a3fe9b',
dataRepository: context.read<DataRepository>(),
),
child: BlocListener<SurveyBloc, SurveyState>(
listener: (context, state) {},
child: Scaffold(
backgroundColor: Color(0xFFF2F2F7),
appBar: _appbar(),
body: stepFormContainer(context),
resizeToAvoidBottomInset: false,
),
),
);
}
Widget saveButton() {
return BlocBuilder<SurveyBloc, SurveyState>(builder: (context, state) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: ElevatedButton.icon(
onPressed: () {
context
.read<SurveyBloc>()
.add(SurveyModeChanged(mode: 'draft'));
},
label: Text('Save')));
});
}
}
This is my Survey event code
abstract class SurveyEvent {}
class SurveyResultChanged extends SurveyEvent {
final String surveyResult;
SurveyResultChanged({this.surveyResult});
}
class SurveyModeChanged extends SurveyEvent {
final String mode;
SurveyModeChanged({this.mode});
}
class SurveyIdChanged extends SurveyEvent {
final String surveyId;
SurveyIdChanged({this.surveyId});
}
class SaveSurveyChanges extends SurveyEvent {}
Survey State dart
class SurveyState {
final User user;
final FormSubmissionStatus formSubmissionStatus;
final String surveyId;
final String mode;
final String surveyResult;
SurveyState(
{#required User user,
#required String surveyId,
String mode,
String surveyResult,
this.formSubmissionStatus = const InitialFormStatus()})
: this.user = user,
this.surveyId = surveyId,
this.mode = mode,
this.surveyResult = surveyResult;
SurveyState copyWith({
User user,
FormSubmissionStatus formSubmissionStatus,
String surveyId,
String mode,
String surveyResult,
}) {
return SurveyState(
user: user ?? this.user,
surveyId: surveyId ?? this.surveyId,
mode: mode ?? this.mode,
surveyResult: surveyResult ?? this.surveyResult,
formSubmissionStatus:
formSubmissionStatus ?? this.formSubmissionStatus);
}
}
SurveyBloc.dart
class SurveyBloc extends Bloc<SurveyEvent, SurveyState> {
final DataRepository dataRepository;
SurveyBloc({
#required User user,
#required String surveyId,
this.dataRepository,
}) : super(SurveyState(user: user, surveyId: surveyId));
#override
Stream<SurveyState> mapEventToState(SurveyEvent event) async* {
if (event is SurveyModeChanged) {
print('mode==>');
print(state.mode);
yield state.copyWith(mode: state.mode);
}
}
}
class SurveyBloc extends Bloc<SurveyEvent, SurveyState> {
final DataRepository dataRepository;
SurveyBloc({
#required User user,
#required String surveyId,
this.dataRepository,
}) : super(SurveyState(user: user, surveyId: surveyId));
#override
Stream<SurveyState> mapEventToState(SurveyEvent event) async* {
if (event is SurveyModeChanged) {
print('mode==>');
print(state.mode);
// This is where the problem occurs. You are emitting the state
// value again and again which is null. Change this:
yield state.copyWith(mode: state.mode);
// into this:
yield state.copyWith(mode: event.mode);
}
}
}
How can to update a Bloc widget from the bloc Widget itself with the Slider?
The Event for the Chart Data is executed from another Widget.
When the data is fetched this Widget is opened.
When I change the Slider I want the chart to be updated withe the date but keep the other data.
Would be too much to fetch all the Data again.
How can I get access only the data changed from the same widget?
I have the following Bloc Builder Widget, bloc_event, bloc and bloc_state
The Widget:
class ChartWidget extends StatelessWidget {
ChartWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
double valueSliderDate;
return BlocBuilder<ChartDataBloc, ChartDataState>(
builder: (context, state) {
if (state is ChartDataLoadInProgress) {
return LoadingIndicator();
} else if (state is ChartDataLoadSuccess) {
final chartData = state.chartData;
final maxValueAll = getMaxValueAll(chartData);
final List<double> dates = getValuesDate(chartData);
valueSliderDate = dates.first;
return Column(children: <Widget>[
Expanded(
child: MyFancyChart(chartData, valueSliderDate),
),
Slider(
min: dates.first,
max: dates.last,
divisions: dates.length,
value: valueSliderDate,
onChanged: (value) {
context.read<ChartDataBloc>().add(DateSliderSet(value));
},
),
]);
} else {
return Container();
}
},
);
}
This is the bloc_event with two events:
abstract class ChartDataEvent {
const ChartDataEvent();
#override
List<Object> get props => []; }
class SpecificIndicatorIdSet extends ChartDataEvent {
const SpecificIndicatorIdSet(this.indicator);
final Indicator indicator;
#override
List<Object> get props => [indicator]; }
class DateSliderSet extends ChartDataEvent {
const DateSliderSet(this.dateSlider);
final double dateSlider;
#override
List<Object> get props => [dateSlider]; }
This is the bloc itself:
class ChartDataBloc extends Bloc<ChartDataEvent, ChartDataState> {
final ChartDataRepository chartDataRepository;
ChartDataBloc({#required this.chartDataRepository}) : super(ChartDataLoadInProgress());
#override
Stream<ChartDataState> mapEventToState(ChartDataEvent event) async* {
if (event is SpecificIndicatorIdSet) {
yield* _mapIndicatorsLoadedToState(event);
} else if (event is DateSliderSet) {
yield* _mapDateSliderToState(event); } }
Stream<ChartDataState> _mapDateSliderToState(
DateSliderSet event
) async* {
try {
final dateSlider = event.dateSlider;
yield DateSliderLoadSuccess(
dateSlider,
);
} catch (_) {
yield DateSliderLoadFailure(); } }
Stream<ChartDataState> _mapIndicatorsLoadedToState(
SpecificIndicatorIdSet event
) async* {
try {
final chartData = await this.chartDataRepository.loadChartData(event.indicator.id);
yield ChartDataLoadSuccess(
sortToListOfLists(chartData),
event.indicator.name
);
} catch (_) {
yield ChartDataLoadFailure(); } } }
This is the bloc_state:
abstract class ChartDataState {
const ChartDataState();
#override
List<Object> get props => []; }
class ChartDataLoadInProgress extends ChartDataState {}
class ChartDataLoadSuccess extends ChartDataState {
final List<List<ChartData>> chartData;
final String titleIndicator;
const ChartDataLoadSuccess(this.chartData,this.titleIndicator);
#override
List<Object> get props => [chartData, titleIndicator];
#override
String toString() => 'ChartDataLoadSuccess { topics: ' + chartData + ' }'; }
class ChartDataLoadFailure extends ChartDataState {}
class DateSliderLoadSuccess extends ChartDataState {
final double dateSlider;
const DateSliderLoadSuccess(this.dateSlider);
#override
List<Object> get props => [dateSlider];
#override
String toString() => 'DateSliderLoadSuccess { dateSlider: ' + dateSlider.toString() + ' }';
}
class DateSliderLoadFailure extends ChartDataState {}
Thanks in advance
Have you tried creating a variable inside your bloc to store the original data?
You would be able to store the data and be able to continue using your bloc and updating your widget.
How to change the widgets in a list item in flutter using bloc pacakage.
Should i use BlockBuilder or listener on the whole ListView.builder or only the individual items.
It would be nice if u share an example or tutorial.
eg If i have a checkbox i need to change its state on clicking it.
These are my Bloc classes
Bloc
const String SERVER_FAILURE_MESSAGE = 'Server Failure';
const String CACHE_FAILURE_MESSAGE = 'Cache Failure';
class MarkAttendanceBloc extends Bloc<MarkAttendanceEvent, MarkAttendanceState> {
final MarkStudentPresent markStudentPresent;
final MarkStudentAbsent markStudentAbsent;
MarkAttendanceBloc({#required this.markStudentPresent,#required this.markStudentAbsent});
#override
MarkAttendanceState get initialState => MarkedInitial();
#override
Stream<MarkAttendanceState> mapEventToState(MarkAttendanceEvent event) async* {
yield MarkedLoading();
if(event is MarkAbsentEvent){
final remotelyReceived = await markStudentAbsent(MarkStudentParams(classId: event.classId, courseId: event.courseId,studentId: event.studentId));
yield* _eitherLoadedOrErrorState(remotelyReceived);
}
else if(event is MarkPresentEvent){
final remotelyReceived = await markStudentPresent(MarkStudentParams(classId: event.classId, courseId: event.courseId,studentId: event.studentId));
yield* _eitherLoadedOrErrorState(remotelyReceived);
}
}
Stream<MarkAttendanceState> _eitherLoadedOrErrorState(
Either<StudentDetailsFacultyFailure,int> failureOrClasses,
) async* {
yield failureOrClasses.fold(
(failure) => MarkedError(_mapFailureToMessage(failure)),
(studentId) => Marked(studentId),
);
}
String _mapFailureToMessage(StudentDetailsFacultyFailure failure) {
switch (failure.runtimeType) {
case ServerError:
return SERVER_FAILURE_MESSAGE;
default:
return 'No internet';
}
}
}
State
abstract class MarkAttendanceState extends Equatable{
const MarkAttendanceState();
}
class MarkedInitial extends MarkAttendanceState{
const MarkedInitial();
#override
List<Object> get props => [];
}
class MarkedLoading extends MarkAttendanceState{
const MarkedLoading();
#override
List<Object> get props => [];
}
class Marked extends MarkAttendanceState{
final int studentId;
Marked(this.studentId);
#override
List<Object> get props => [studentId];
}
class MarkedError extends MarkAttendanceState{
final String errorMessage;
MarkedError(this.errorMessage);
#override
List<Object> get props => [errorMessage];
}
Event
import 'package:equatable/equatable.dart';
abstract class MarkAttendanceEvent extends Equatable {
const MarkAttendanceEvent();
}
class MarkPresentEvent extends MarkAttendanceEvent {
final int studentId;
final int courseId;
final int classId;
MarkPresentEvent(this.studentId, this.courseId, this.classId);
#override
List<Object> get props =>[studentId,courseId,classId];
}
class MarkAbsentEvent extends MarkAttendanceEvent {
final int studentId;
final int courseId;
final int classId;
MarkAbsentEvent(this.studentId, this.courseId, this.classId);
#override
List<Object> get props =>[studentId,courseId,classId];
}
Maybe by now you have found a solution but this is how i managed to achieve the same functionality using flutter cubits.
This code is hand written and not tested but it should guide you to achieve your goal
1 Declare the class objects
class ClassItem{
int? price;
bool isChecked;
ClassItem({
this.price,
this.isChecked=false,
});
}
class ClassOverall{
List<ClassItem> items;
double? total;
ClassOverall(this.items,this.total);
}
Declare the cubit class
class OverallCubit extends Cubit<ClassOverall> {
OverallCubit(ClassOverallinitialState) : super(initialState);
void checkUncheckCart(int index) {
if (!state.items
.elementAt(index).isChecked) {
state.items
.elementAt(index).isChecked =
!state.items
.elementAt(index).isChecked;
var t_total = double.tryParse(state.items
.elementAt(index).price!)! * 1;
emit(OverallCubit (state.items,state.total));
} else {
state.items.elementAt(index).isChecked =
!state.items
.elementAt(index).isChecked;
emit(OverallCubit (state.items,state.total));
}
calculateTotal();
}
void calculateTotal() {
var tot = 0.0;
for (var tick in state.items) {
if (tick.isChecked) {
tot = (tick.t_total! + tot);
}
}
emit(OverallCubit (state.items,tot));
}
}
Declare the top class widget to hold the state
class TopState extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => OverallCubit(ClassOverall(items,0)),//fetch items from your source
child: Home(),
);
}
}
Declare the stateful widget and add a bloc builder
class Home extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<Home> {
#override
Widget build(BuildContext context) {
return BlocBuilder<OverallCubit, ClassOverall>(
builder: (ctx, state) {
return Column(children:[
ListView.builder(
padding: EdgeInsets.all(0.0),
shrinkWrap: true,
itemCount: state.items.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {
ctx
.read<OverallCubit>()
.checkUncheckCart(index);
},
tileColor: state.elementAt(index).isChecked ? Colors.red : Colors.white
title: Text(state.items.elementAt(index).price!),
);
}),
Text(state.total.toString),
]);
});
}
}