Advanced Usage
This section provides an overview of some advanced API features.
Update Query with Controller
CozyQueryController
The CozyQueryController
exposes an API that helps you apply predicates to your query and modify the returned data. This controller allows you to filter, join, order, and customize your queries efficiently.
Example Usage
final controller = CozyQueryController<MyModel>();
await controller.addWhere([PredicateGroup(predicates: [Predicate.equals('field', 'value')])]);
await controller.addJoin([Join(table: 'other_table', condition: 'other_table.id = my_table.other_id')]);
await controller.orderBy([OrderBy(field: 'created_at', direction: OrderDirection.desc)]);
await controller.addCustomQuery(CozyQueryBuilder<MyModel>());
await controller.reset();
Practical Example
Here is a practical example of how to use CozyQueryController to filter recipes based on user input in a search bar:
class RecipeListView extends StatefulWidget {
_RecipeListViewState createState() => _RecipeListViewState();
}
class _RecipeListViewState extends State<RecipeListView> {
static final CozyQueryController<Recipe> _queryController = CozyQueryController<Recipe>();
final CozyQueryListener<Recipe> _recipeQuery = CozyData.queryListener<Recipe>(controller: _queryController);
final TextEditingController _searchController = TextEditingController();
/// This method filters the data to retrieve all recipes where the name or any ingredient contains the value from the [_searchController].
/// It uses the `CozyQueryController` to apply a predicate that checks for the presence of the search term in either the recipe name or the ingredients list.
/// The predicate is structured to use an "OR" condition to ensure that either field matching the search term will return the recipe.
void _updateQuery() async {
await _queryController.addWhere([
PredicateGroup(
predicates: [
Predicate.contains("name", _searchController.text),
],
type: PredicateGroupType.or,
subgroups: [
PredicateGroup(
predicates: [
Predicate.contains("ingredients", _searchController.text),
],
),
],
)
]);
}
void initState() {
super.initState();
/// Listen to the search and then filter the data based on the search
_searchController.addListener(_updateQuery);
}
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
_buildSearchBar(),
_buildRecipeList(),
],
),
);
}
Widget _buildSearchBar() {
return SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(13),
child: CupertinoSearchTextField(
placeholder: 'Search for recipes or ingredients',
backgroundColor: const Color.fromRGBO(227, 227, 233, 1),
controller: _searchController,
),
),
);
}
Widget _buildRecipeList() {
return SliverToBoxAdapter(
child: ListenableBuilder(
listenable: _recipeQuery,
builder: (context, _) {
final recipes = _recipeQuery.items;
if (recipes.isEmpty) {
return const Center(
child: Text(
"Please click the + button to add a new recipe\n\nOnce added, you can edit it by tapping on it",
textAlign: TextAlign.center,
),
);
}
return Container(
margin: const EdgeInsets.symmetric(horizontal: 18),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(13),
),
child: SingleChildScrollView(
child: Column(
children: List.generate(
recipes.length,
(index) {
final recipe = recipes[index];
final isLastItem = index == recipes.length - 1;
return Column(
children: [
ListTile(
minVerticalPadding: 45,
title: Text(
recipe.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
trailing: const Icon(
Icons.arrow_forward_ios,
color: Colors.grey,
size: 15,
)
),
if (!isLastItem)
Divider(
height: 1,
indent: 15,
color: Colors.grey.shade200,
),
],
);
},
),
),
),
);
},
),
);
}
void dispose() {
_recipeQuery.dispose();
_searchController.dispose();
super.dispose();
}
}
In this example, the CozyQueryController
is used to filter recipes based on the user's input in a search bar. The _updateQuery
method applies a predicate to filter recipes where the name or ingredients contain the search term. The ListenableBuilder
widget listens to changes in the query and updates the UI accordingly.