Flutter : Display Values inside GridView depending on Selected Category - flutter

I have an app that displays _customCard which is customized card inside GridView. I want to control the contents of the cards inside GridView so it could be changed according to selected value SelectedCategory of 6 different categories.
Here is where I control SelectedCategory:
_favouritePressed(int index){
setState(() {
selectedIndex = index;
});
}
Here is the code of GridView:
GridView.count(
crossAxisCount: 2,
children: <Widget>[
_customCard(
imageUrl: "assassin.png", item: "game", price: "\$50", count: 1
),
_customCard(
imageUrl: "sedan.png", item: "car", price: "\$25", count: 4
),
_customCard(
imageUrl: "blouse.png", item: "T-shirt", price: "\$20", count: 2
),
_customCard(
imageUrl: "toy.png", item: "kids", price: "\$2", count: 3
),
],
),

I am not sure I understand your question but I will take a shot at the solution:
GridView.count(
crossAxisCount: 2,
children: <Widget>[
if (selectedIndex==0)
_customCard(
imageUrl: "assassin.png", item: "game", price: "\$50", count: 1
),
if (selectedIndex==1)
_customCard(
imageUrl: "sedan.png", item: "car", price: "\$25", count: 4
),
if (selectedIndex==2)
_customCard(
imageUrl: "blouse.png", item: "T-shirt", price: "\$20", count: 2
),
if (selectedIndex==3)
_customCard(
imageUrl: "toy.png", item: "kids", price: "\$2", count: 3
),
],
),
Sorry if I misunderstood your question.

Related

Retrieve specific value from Hive Box

In my app, I am using Hive to store data locally. My box is called "favorites" and I managed to store the data in the box with this code:
_save() {
final recipeData = Recipe(
title: widget.recipeDocument['title'],
id: widget.recipeDocument['id'],
price: widget.recipeDocument['price'],
url: widget.recipeDocument['url'],
servings: widget.recipeDocument['servings'],
calories: widget.recipeDocument['calories'],
carbs: widget.recipeDocument['carbs'],
protein: widget.recipeDocument['protein'],
fat: widget.recipeDocument['fat'],
ingredients: widget.recipeDocument['ingredients'],
instructions: widget.recipeDocument['instructions'],);
print('Generated recipeData final $recipeData');
String json =jsonEncode(recipeData);
print('Generated json $json');
final box = Hive.box('favorites'); //<- get an already opened box, no await necessary here
// save recipe information
final Id = widget.recipeDocument['id'];
box.put(Id,json);
On my favorite page, I want to display the title and price in a ListView.
I get data from the box like this:
body: ValueListenableBuilder(
valueListenable: Hive.box('favorites').listenable(),
builder: (context, box, child) {
var box = Hive.box('favorites');
List post = List.from(box.values);
print('List is $post');
The list contains the following:
[
{
"url": "http for URL",
"title": "Bananabread",
"price": "0,77",
"calories": "234",
"carbs": "12",
"fat": "1",
"id": "1",
"protein": "34",
"servings": 1,
"ingredients": [
"2 bananas",
"30 g flour",
"2 eggs"
],
"instructions": [
"1. mix banana and egg.",
"2. add flour.",
"3. bake and enjoy"
]
}
]
Let's say I only want to retrieve the title and price from that. How do I do so?
I tried this:
return ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Text('This shows favorites'),
...post.map(
(p) => ListTile(
title: Text(p[1]),
trailing: Text(p[2]),
),
),
],
);
But this only returns "U" and "R"...so the letters from the word URL, I guess?
Try this. You are accessing the key of the map in the list.
return ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Text('This shows favorites'),
...post.map(
(p) => ListTile(
title: Text(p['url'].toString()),
trailing: Text(p['title'].toString()),
),
),
],
);

How to get the index value whilst not getting duplicates within ListView.builder?

I'm trying to show the week's budget spending & timeline only when the user has put in the spending information.
This is the expected result and all seems to be working nicely until I add in more than just one spending in each week.
Here's what happens:
The problem that I understand is that the ListView.builder gets the date that is between "Initial" and "End" and builds the widgets. So because there's 2 spending between those dates, then it builds 2 of those widgets. The problem is I just can't seem to figure out a way to show them without duplication.
Here's my code:
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
controller: ScrollController(),
itemCount: snapshot.data!.length,
padding: const EdgeInsets.only(bottom: 8),
itemBuilder: (context, index) {
final spending = snapshot.data![index];
DateTime spendingDate = DateTime.parse(spending.date);
var initial =
DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
var end = DateTime(endDate.year, endDate.month, endDate.day + 1);
return spendingDate.isAfter(initial) && spendingDate.isBefore(end)
? Column(
children: [
WeekDivider(label: label, dateEstimation: dateEstimation),
WeeklySpendingStream(
color: color,
snapshot: snapshot,
initialDate: initialDate,
endDate: endDate,
),
],
)
: const SizedBox();
},
);
}
WeeklySpendingStreamCode:
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
controller: ScrollController(),
itemCount: snapshot.data!.length,
padding: const EdgeInsets.only(bottom: 8),
itemBuilder: (context, index) {
final spending = snapshot.data![index];
DateTime spendingDate = DateTime.parse(spending.date);
var initial =
DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
var end = DateTime(endDate.year, endDate.month, endDate.day + 1);
if (spendingDate.isAfter(initial) && spendingDate.isBefore(end)) {
return SwipeActionCell(
editModeOffset: 0,
fullSwipeFactor: 0.50,
key: ObjectKey(snapshot.data![index]),
trailingActions: [
SwipeAction(
performsFirstActionWithFullSwipe: true,
color: Colors.transparent,
content: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.red,
),
child: getIconButton(Colors.red, IconlyBold.delete)),
onTap: (handler) async {
handler(true);
await Future.delayed(const Duration(milliseconds: 100));
snapshot.data!.removeAt(index);
SpendingDatabaseHelper.instance.removeMethod(spending.id!);
},
),
],
child: SpendingCard(
beneficiary: spending.beneficiary,
budgetSpent: currency.format(int.parse(spending.budgetSpent)),
date: DateFormat("dd-MM-yyyy")
.format(DateTime.parse(spending.date)),
colorValue: color,
),
);
} else {
return const SizedBox();
}
},
);
}
The output of snapshot.data:
[
{id: 8, budgetName: 🍣 Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-21},
{id: 7, budgetName: 🍣 Food & Beverage, beneficiary: dfgvsd, budgetSpent: 1, date: 2022-02-14},
{id: 4, budgetName: 🍣 Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-11},
{id: 10, budgetName: 🍣 Food & Beverage, beneficiary: ddd, budgetSpent: 1, date: 2022-02-11},
{id: 5, budgetName: 🍣 Food & Beverage, beneficiary: asxasd, budgetSpent: 1, date: 2022-02-06}
]
Would really appreciate any suggestions/ideas of how this can be resolved.
Thanks in advance!
Nevermind, I somehow found the solution by getting the data using ".where" and checking whether it is empty or not. It worked nicely.
var initial = DateTime(initialDate.year, initialDate.month, initialDate.day - 1);
var end = DateTime(endDate.year, endDate.month, endDate.day + 1);
final spending = snapshot.data!.where((s) =>
DateTime.parse(s.date).isAfter(initial) &&
DateTime.parse(s.date).isBefore(end));
return spending.isNotEmpty ||
DateTime.now().isAfter(initial) && DateTime.now().isBefore(end)
? spending.isEmpty
? Column(
children: [
WeekDivider(label: label, dateEstimation: dateEstimation),
const Padding(
padding: EdgeInsets.only(top: 8, bottom: 16),
child: Text(
'No spending this week',
style: kCaption,
),
),
],
)
: ListView(
shrinkWrap: true,
controller: ScrollController(),
padding: const EdgeInsets.only(bottom: 8),
children: [
Column(
children: [
WeekDivider(label: label, dateEstimation: dateEstimation),
WeeklySpendingStream(
color: color,
snapshot: snapshot,
initialDate: initialDate,
endDate: endDate,
),
],
)
],
)
: const SizedBox();
}
I think your problem raised because of you just extract the database file without filtering so do this use .toSet() or assign the extracted data to a variable as a map or Set and use .toSet().

How can I insert new food data to specific category id

final List <Category> _categories = [
Category(
id: '1',
title: 'Poultry',
food: [
Food(
id: '1',
title: 'Chicken 1',
description: "qdwwqd",
price: 500.00,
image: "https://jb-ph-cdn.tillster.com/menu-images/prod/45df1872-c7f7-4b3d-baa9-1b0c4f56a5cc.png",
choice: [],
),
],
),
Category(
id: '2',
title: 'Vegetables',
food: [
Food(
id: '1',
title: 'Cabbage',
description: "qdwwqd",
price: 500.00,
image: "https://jb-ph-cdn.tillster.com/menu-images/prod/45df1872-c7f7-4b3d-baa9-1b0c4f56a5cc.png",
choice: [],
),
],
),
]
'''
In order to insert new data into the food array, first you need to find the correct category:
String myID = '1';
int index = _categories.indexWhere((cat) => cat.id == myID);
Once you did that, it is quite simple:
_categories[index].food.add(Food());

Flutter how to add grouped data to a list

How can i make a grouped json data to a list in flutter? I have grouped jsondata.
final data = body.data['items']; // gets json data here
final uniqueSetOfChapters =groupBy(data, (dynamic obj) => obj['chapter']); // grouping it here
uniqueSetOfChapters.forEach((key, value) {
print('$key : : $value');
});
As a result i'm getting a grouped data as follows
Measurement : : [
{sequenceno: 193, _id: 5dc1, chapter: Measurement, title: Measuring Length, package_description: Let us learn about ‘Measurement using Length'., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 193, _id: 5d99, chapter: Measurement, title: Measuring Weight, package_description: Let us learn about ‘Measuring Weight’., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 1933, _id: 5d99, chapter: Measurement, title: Measuring Capacity, package_description: This module introduces how to measure the capacity of a container., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 193, _id: 5ef4, chapter: Measurement, title: Revision - Measuring Length, package_description: In this module, we will revise about measurement using length., age_level: [99, 6], pkg_sequence: 2514],
Data Handling : : [
{sequenceno: 193, _id: 5e23, chapter: Data Handling, title: Bar chart, package_description: This module helps to understand how to represent data., age_level: [99, 6], pkg_sequence: 2511},
{sequenceno: 193, _id: 5f15, chapter: Data Handling, title: Revision - Bar chart, package_description: Let us revise some activities on presenting data in the form of graphs., age_level: [99, 6], pkg_sequence: 251}
]
How can i make this grouped data to a list? I have created a model for this as follows
class Titles{
String? sequenceno;
String? id;
String? chapter;
String? title;
String? packageDescription;
String? ageLevel;
String? pkgSequence;
String? packagescors;
Titles({
this.sequenceno,
this.id,
this.chapter,
this.title,
this.packageDescription,
this.ageLevel,
this.pkgSequence,
this.packagescors,
});
factory Titles.fromMap(Map<String, dynamic> map) {
return Titles(
sequenceno: map['sequenceno'],
id: map["_id"],
chapter: map['chapter'],
title: map['title'],
packageDescription: map['package_description'],
ageLevel: map['age_level'],
pkgSequence: map['pkg_sequence'],
// packagescors: map['packagescors'],
);
}
Map<String, dynamic> toMap(){
var map = <String,dynamic>{
"sequenceno": sequenceno,
"_id": id,
"chapter": chapter,
"title": title,
"package_description": packageDescription,
"age_level": ageLevel,
"pkg_sequence": pkgSequence,
"packagescors": packagescors,
};
return map;
}}
How can I add this grouped data to a list??
You can try with grouped_list package: https://pub.dev/packages/grouped_list
Output sample:
Code snippet:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: Appbar(title: "Titles",),
body: Container(
child: GroupedListView<dynamic, String>(
elements: measurements,
groupBy: (element) => element.chapter,
groupComparator: (value1, value2) => value2.compareTo(value1),
order: GroupedListOrder.ASC,
useStickyGroupSeparators: true,
groupSeparatorBuilder: (String value) => Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
value,
textAlign: TextAlign.start,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor),
),
),
itemBuilder: (c, element) {
return Column(
children: <Widget>[
ListTile(
title: Text(
element.title,
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
subtitle: Text(
element.packageDescription,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, ),
),
onTap: () => {},
),
],
);
},
),
),
);
}
I assume you want to convert a list of map :
measurement = [{'sequenceno': '193', '_id': '5d99',... }, {'sequenceno': '1933', '_id': '5d99', ..}, {...}, {...}]
into a list of Titles.
What you can do is :
var titleList = [for (var map in measurement) Titles.fromMap(map) ];
For information, you don't need to use a Factory constructor. The following constructor should work as well :
Titles.fromMap(Map<String, dynamic> map) :
sequenceno = map['sequenceno'],
id = map["_id"],
chapter = map['chapter'],
title = map['title'],
packageDescription = map['package_description'],
ageLevel = map['age_level'],
pkgSequence = map['pkg_sequence'];

Flutter: Select Card inside GridView

I have an app which displays data in Cards inside GridView like so:
GridView.count(
crossAxisCount: 2,
children: <Widget>[
_customCard(
imageUrl: image1, item: item1, price: price1, count: count1
),
_customCard(
imageUrl: image2, item: item2, price: price2, count: count2
),
_customCard(
imageUrl: image3, item: item3, price: price3, count: count3
),
_customCard(
imageUrl: image4, item: item4, price: price4, count: count4
),
],
),
I want to get the specified card name when it is pressed depending on its index inside a List as we do in ListView.
class item {
final String name;
final int count;
final String imageUrl;
final double price;
item({this.name, this.imageUrl, this.count, this.price});
}
List<item> tops = [
new item(
imageUrl: "tshirt.png",
name: "T-shirt",
count: 0,
price: 0.50
),
new item(
imageUrl: "shirt.png",
name: "Shirt",
count: 0,
price: 0.80
),
Is there a way to do so with GridView or shall I try something else?
You can use Gridview.builder and use its index to get the related object from list:
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
physics: ScrollPhysics(),
itemCount: _customCards.length,
itemBuilder: (BuildContext context, int index){
return Inkwell(child:_customCards(
imageUrl: image[index], item: item[index], price: price[index], count: count[index]),
onTap(){
print(tops[index]);
}
),
}
);*