blowe_bloc 0.4.0
blowe_bloc: ^0.4.0 copied to clipboard
An advanced Flutter package for state management and business logic components, extending flutter_bloc.
blowe_bloc
is an advanced Flutter package for state management and business logic components, extending flutter_bloc
. It provides a comprehensive set of tools to streamline the development of complex applications with clear separation of concerns, efficient state management, and enhanced UI components. By leveraging the powerful BLoC pattern, blowe_bloc
ensures your app's logic is both scalable and maintainable.
In addition to the core state management features, blowe_bloc
now includes advanced search capabilities and history management, making it easier to implement robust search functionalities in your Flutter applications.
Features #
-
Advanced BLoC Components: Includes specialized BLoCs for handling data loading, pagination, and data watching. Each BLoC is designed to emit specific states (
BloweInProgress
,BloweCompleted
,BloweError
) for better state management. -
Advanced Search Functionality: New
BloweSearchBloc
andBloweSearchDelegate
components for implementing robust search capabilities with automatic history management and debouncing support. -
Comprehensive Models: Models such as
BloweNoParams
for operations requiring no parameters,BlowePaginationModel
for managing paginated data,BloweSerializableItem
for serializable items, andBloweSearchParams
for search parameter handling. These models integrate seamlessly with the BLoCs to handle various data scenarios. -
Reactive Widgets: A variety of widgets including
BloweBlocButton
,BloweBlocListener
,BloweBlocSelector
,BloweMultiBlocSelector
,BlowePaginationListView
, and form fields likeBloweTextFormField
,BloweDropdownButtonFormField
,BloweBoolFormListTile
,BloweRadiusForm
, and the newly addedBloweNumberFormListTile
. These widgets are designed to react to state changes efficiently. -
Form Field Widgets: Specialized form field widgets that offer enhanced functionality, validation, and customizability. These include
BloweTextFormField
for text input (now with multi-line support),BloweDropdownButtonFormField
for dropdowns,BloweBoolFormListTile
for switch and checkbox tiles (with adaptive support),BloweRadiusForm
for radio list tiles, andBloweNumberFormListTile
for number selection with increment and decrement buttons. -
Seamless Integration: Built on top of
flutter_bloc
for easy integration into your existing Flutter projects. The package ensures minimal boilerplate while offering maximum functionality and flexibility. -
Error Handling: Enhanced error handling across all BLoCs and widgets, providing robust feedback mechanisms and state recovery options.
Blowe Search #
blowe_bloc
introduces powerful search capabilities with the new BloweSearchBloc
and BloweSearchDelegate
. These components provide a robust solution for implementing search functionalities in your Flutter applications with ease.
BloweSearchBloc #
BloweSearchBloc
extends the BlowePaginationBloc
to manage search operations, including the ability to add, remove, and clear search history. It uses SharedPreferences
to persist the search history, allowing for a seamless user experience.
Example
class BookSearchBloc extends BloweSearchBloc<BookModel, BookSearchParams> {
@override
Future<BlowePaginationModel<BookModel>> load(BookSearchParams params, int page) {
// Implement the search logic here
}
@override
BookModel fromJson(Map<String, dynamic> json) {
return BookModel.fromJson(json);
}
}
BloweSearchDelegate #
BloweSearchDelegate
integrates with BloweSearchBloc
to handle the UI aspect of search functionalities. It provides automatic history management, debouncing support, and a customizable search experience.
Example
class BookSearchDelegate extends BloweSearchDelegate<BookSearchBloc,BookModel, BookSearchParams> {
BookSearchDelegate(BookSearchBloc bloc)
: super(
bloc: bloc,
itemBuilder: (context, item, close, save) {
return ListTile(
title: Text(item.title),
onTap: () {
save(item); // Save to history
close(context, item); // Close the delegate with the selected item
},
);
},
paramsProvider: (query) => BookSearchParams(query),
);
}
Key Features #
- Automatic History Management: The
BloweSearchBloc
handles adding, removing, and clearing search history, ensuring a user-friendly experience. - Debouncing Support: The
BloweSearchDelegate
includes a debouncer to manage search queries efficiently, reducing unnecessary load on the backend. - Customizable Search Experience: The search delegate and bloc can be customized to fit the specific needs of your application, providing flexibility in how search results are displayed and managed.
By leveraging these new search components, you can enhance your Flutter applications with advanced search functionalities that are both powerful and easy to integrate.
Blowe Logic #
BloweLoadBloc #
BloweLoadBloc is an abstract class that extends BloweBloc
and provides a structure for loading data using a provided load method. This class is designed to handle data fetching operations, emitting different states such as BloweInProgress
, BloweCompleted<T>
, and BloweError
based on the result of the data loading process.
Example
class MyBloweLoadBloc extends BloweLoadBloc<String, BloweNoParams> {
@override
Future<String> load(BloweNoParams params) => Future<String>.delayed(
const Duration(seconds: 2),
() => 'Blowe Load Bloc Completed!',
);
}
BloweWatchBloc #
BloweWatchBloc is an abstract class that extends BloweBloc
and provides a structure for watching data changes using a provided watch method. This class is designed to handle real-time data updates by subscribing to a stream and emitting different states such as BloweInProgress
, BloweCompleted<T>
, and BloweError
based on the data changes.
Example
class MyBloweWatchBloc extends BloweWatchBloc<String, BloweNoParams> {
@override
Stream<String> watch(BloweNoParams params) => Stream<String>.periodic(
const Duration(seconds: 2),
(count) => 'Blowe Watch Bloc Update $count',
);
}
BlowePaginationBloc #
BlowePaginationBloc is an abstract class that extends BloweBloc
and provides a structure for handling paginated data using a provided load method. This class is designed to handle data fetching operations in a paginated manner, emitting different states such as BloweInProgress
, BloweCompleted<T>
, and BloweError
based on the result of the data loading process.
Example
class MyBlowePaginationBloc
extends BlowePaginationBloc<MyPaginationModel, BloweNoParams> {
@override
Future<MyPaginationModel> load(BloweNoParams params, int page) =>
Future<MyPaginationModel>.delayed(
const Duration(seconds: 2),
() => MyPaginationModel(data: List.generate(10, (index) => 'Item $index')),
);
}
class MyPaginationModel extends BlowePaginationModel<String> {
MyPaginationModel({required List<String> data}) : super(data: data);
}
Blowe Logic Widgets #
BloweBlocSelector #
BloweBlocSelector is a widget that uses a BlocSelector
to determine if the widget should be enabled. It rebuilds based on the state of the specified BloweBloc
.
Example
BloweBlocSelector<MyBloweBloc>(
builder: (context, enabled) {
return FloatingActionButton(
onPressed: enabled
? () {
context.read<MyBloweBloc>().add(
const BloweFetch(BloweNoParams()),
);
}
: null,
child: const Icon(Icons.add),
);
},
)
BloweMultiBlocSelector #
BloweMultiBlocSelector is a widget that monitors multiple BloweBlocs
and determines if the widget should be enabled based on the state of all provided BloweBlocs
.
Example
BloweMultiBlocSelector(
blocs: [
MyBloweBloc1(),
MyBloweBloc2(),
];,
builder: (context, enabled) {
return FloatingActionButton(
onPressed: enabled
? () {
// Your action here
}
: null,
child: const Icon(Icons.add),
);
},
)
BloweBlocListener #
BloweBlocListener is a widget that listens to the state changes of a BloweBloc
and triggers the corresponding callback functions for each state type.
Example
BloweBlocListener<MyBloweBloc, String>(
onCompleted: (context, state) {
// Handle completed state
},
onError: (context, state) {
// Handle error state
},
onLoading: (context, state) {
// Handle loading state
},
onInitial: (context, state) {
// Handle initial state
},
child: const MyChildWidget(),
)
BloweBlocButton #
BloweBlocButton is a button widget that uses a BloweBloc
to determine if the button should be enabled. It rebuilds based on the state of the specified BloweBloc
.
Example
BloweBlocButton<MyBloweLoadBloc, ElevatedButton>(
text: 'Load Data',
onPressed: () {
context.read<MyBloweLoadBloc>().add(
const BloweFetch(BloweNoParams()),
);
},
)
BlowePaginationListView #
BlowePaginationListView is a widget that displays a paginated list of items using a BlowePaginationBloc
. It handles loading, error, and completed states of the BlowePaginationBloc
, providing a seamless pagination experience. This widget supports filtering, grouping, and pull-to-refresh functionality.
Example
BlowePaginationListView<MyBlowePaginationBloc, MyItem, MyParams, MyGroup>(
itemBuilder: (context, item) => ListTile(
title: Text(item.name),
),
paramsProvider: () => MyParams(),
emptyWidget: Center(child: Text('No items found')),
padding: EdgeInsets.all(8.0),
filter: (item) => item.isVisible,
groupBy: (item) => item.category,
groupHeaderBuilder: (context, group, items) => Padding(
padding: EdgeInsets.all(8.0),
child: Text('Category: $group', style: TextStyle(fontSize: 18)),
),
)
Blowe Form Widgets #
BloweTextFormField #
A text form field widget that supports optional obscuring of text, custom validation, and custom icons. This widget is designed to be extended for creating specialized text form fields with unique properties, allowing for dynamic customization and validation within a form.
Example
class EmailTextFormField extends BloweTextFormField {
EmailTextFormField({
super.key,
super.controller,
super.enabled,
super.onEditingComplete,
super.textInputAction,
}) : super(
validator: (context, value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
return 'Please enter a valid email';
}
return null;
},
keyboardType: TextInputType.emailAddress,
labelText: (context) => 'Email',
);
}
// Usage example in a form
final _emailController = TextEditingController();
EmailTextFormField(
controller: _emailController,
enabled: true,
onEditingComplete: () {
// Handle the editing complete action
},
textInputAction: TextInputAction.next,
)
BloweDropdownButtonFormField #
A dropdown button form field widget that allows customization of the dropdown items, icon, suffix icon, label text, and validator. This widget is designed to be extended for creating specialized dropdown form fields with unique properties, enabling dynamic customization and validation within a form.
Example
class CountryDropdownButtonFormField extends BloweDropdownButtonFormField<String> {
CountryDropdownButtonFormField({
super.key,
required List<String> countries,
required ValueChanged<String?> onChanged,
String? initialValue,
}) : super(
items: countries,
onChanged: onChanged,
itemBuilder: (context, country) => DropdownMenuItem(
value: country,
child: Text(country),
),
labelText: (context) => 'Country',
value: initialValue,
);
}
// Usage example in a form
final _selectedCountry = 'Argentina';
CountryDropdownButtonFormField(
countries: ['USA', 'Canada', 'Mexico', 'Argentina'],
onChanged: (value) {
setState(() =>_selectedCountry = value);
},
initialValue: _selectedCountry,
)
BloweBoolFormListTile #
A form field widget that wraps a SwitchListTile
or CheckboxListTile
. The BloweBoolFormListTile
widget provides a way to use a switch or checkbox within a form, utilizing a BloweBoolFormController
to manage its state. This widget supports customization of the switch's or checkbox's appearance and behavior, including validation, enabling/disabling, and visual styling.
Example
final _controller = BloweBoolFormController(initialValue: true);
BloweBoolFormListTile(
controller: _controller,
title: (context) => 'Enable notifications',
type: BloweBoolListTileType.switchTile,
);
BloweRadiusForm #
A form field widget that manages a list of radius list tiles. The BloweRadiusForm
widget provides a way to manage a list of radius list tiles within a form, utilizing a BloweRadiusFormController
to manage its state. This widget supports customization of the appearance and behavior, including validation, enabling/disabling, and visual styling.
Example
final _controller = BloweRadiusFormController<int>(initialValue: 1);
BloweRadiusForm<int>(
controller: _controller,
items: [1, 2, 3],
titleBuilder: (context, item) => 'Item: $item',
validator: (context, value) {
if (value == null) {
return 'Please select an item.';
}
return null;
},
);
BloweNumberFormListTile #
A form field widget that displays a number selector with increment (+) and decrement (-) buttons. The BloweNumberFormListTile
widget provides a simple way to manage numerical input within a form, utilizing a BloweNumberFormController
to manage its state. This widget supports customization of the appearance and behavior, including validation, enabling/disabling, and visual styling.
Example
final _controller = BloweNumberFormController(initialValue: 0);
BloweNumberFormListTile(
controller: _controller,
title: (context) => 'Select Quantity',
validator: (context, value) {
if (value == null || value < 0) {
return 'Please select a valid quantity.';
}
return null;
},
);
Blowe Models #
BloweNoParams #
BloweNoParams is a simple class that represents a scenario where no parameters are required. This can be used in situations where an operation or function does not need any input parameters.
Example
const params = BloweNoParams();
// Use BloweNoParams in an operation that doesn't require parameters.
myBloc.add(BloweFetch(params));
BlowePaginationModel #
BlowePaginationModel is a class designed to handle paginated data. It provides a structure to manage items of type T
along with the total count of items. This model is typically used in conjunction with BlowePaginationBloc
to manage pagination logic in your application.
Example
class NoteModel {
// Define your NoteModel properties and methods here.
NoteModel.fromJson(Map<String, dynamic> json) {
// Parse the JSON to initialize NoteModel properties.
}
}
class NotesPaginationModel extends BlowePaginationModel<NoteModel> {
const NotesPaginationModel({
required super.totalCount,
required super.items,
});
factory NotesPaginationModel.fromJson(List<Map<String, dynamic>> json) {
final items = json.map(NoteModel.fromJson).toList();
return NotesPaginationModel(
totalCount: items.length,
items: items,
);
}
}
Author #
Developed by Santiago Gonzalez Fernandez.