How to change state of individual list items using bloc flutter?
Asked Answered
F

1

8

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];

}
Foliate answered 26/6, 2020 at 13:53 Comment(0)
T
2

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);
    }
  1. 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));
     }
     }
    
  2. 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(),
            );
          }
        }
    
  3. 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),
     ]);
                                      });
     }
    
     }
    
Transparency answered 22/5, 2021 at 11:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.