eventful_widget

A Flutter package that uses bloc to encourage separation of logic from looks.

About

This package provides two useful abstract widgets -- EventfulWidget and StateInjectedWidget. Extending these classes allows for simple and clean state management. Proper use of this package will give you a clear path to easily test business logic components as well as UI components.

Usage

Start by defining your events and states.

enum  CoolEvent {
	somethingCool,
	somethingEvenCooler,
}

@immutable
class  CoolState {
	CoolState(this.message);
	final  String  message;
}

With these, we can now create our BLoC.

class CoolBloc extends Bloc<CoolEvent, CoolState> {}

Let's go ahead and add some logic to the constructor of our bloc.

class  CoolBloc  extends  Bloc<CoolEvent, CoolState> {
	CoolBloc() : super(CoolState('waiting for something cool to happen...')) {
		on<CoolEvent>((event, emit) {
			String  message = '';
			switch (event) {
				case  CoolEvent.somethingCool:
				message = 'waiting for something cool to happen...';
				break;
				case  CoolEvent.somethingEvenCooler:
				message = 'something REALLY cool happened!';
				break;
				default:
				message = 'this shouldn\'t ever happen';
			}
			emit(CoolState(message)); // this is what triggers state change in your widget
		});
	}
}

Next, create a widget which will use your new bloc and delegate drawing by extending EventfulWidget and implementing builder.

class  CoolWidget  extends  EventfulWidget<CoolEvent, CoolState> {
	CoolWidget(Bloc<CoolEvent, CoolState> bloc) : super(bloc);
	
	@override
	StateInjectedWidget<CoolEvent, CoolState> builder(BuildContext  context, CoolState  state, void Function(CoolEvent)? onEvent) => CoolWidgetView(state, onEvent);
}

Finally, it's time to create the widget that will actually "draw" your UI. Make sure to extend StateInjectedWidget.

class  CoolWidgetView  extends  StateInjectedWidget<CoolEvent, CoolState> {
	CoolWidgetView(CoolState  state, void  Function(CoolEvent)? onEvent) : super(state, onEvent: onEvent);

	@override
	Widget  builder(BuildContext  context, CoolState  state, void  Function(CoolEvent)? onEvent) {
		return  ElevatedButton(
		onPressed: () {
			if (state.message == 'waiting for something cool to happen...') {
			onEvent!(CoolEvent.somethingEvenCooler);
			} else {
			onEvent!(CoolEvent.somethingCool);
			}
		},
		child: Text(state.message),
		);
	}
}

Now you can use CoolWidget like so:

void main() {
	final bloc = CoolBloc();
	
	runApp(MaterialApp(
		home: Center(
		child: CoolWidget(bloc),
	));
}