I'm struggling to understand how I can filter data by ID using providers. The approach I have tried yields the below error:
Class '_InternalLinkedHashMap<String, Object>' has no instance getter 'id'.
Receiver: _LinkedHashMap len:8
Tried calling: id
Given my little experience in Flutter, any help or suggestion would be highly appreciated. The code I have written is below:
class PopularDishesProvider with ChangeNotifier {
final Map<String, dynamic> _popularDishes = { //This is the JSON map that I would like to filter from
"data": [
{
"id": "1",
"name": "Chicken Tandoor Combo",
"restaurantName": "Tandoori House",
"price": "455",
"rating": "4.3",
"totalRatings": "154",
"image": "assets/images/Rectangle 17323.png",
"isFavourite": false
},
{
"id": "2",
"name": "Pan Cake",
"restaurantName": "The Pancake Centre",
"price": "250",
"rating": "4.7",
"totalRatings": "256",
"image": "assets/images/Rectangle 17324.png",
"isFavourite": false
},
{
"id": "3",
"name": "Salad",
"restaurantName": "The Pancake House",
"price": "180",
"rating": "4.1",
"totalRatings": "203",
"image": "assets/images/Rectangle 17325.png",
"isFavourite": false
},
{
"id": "4",
"name": "Roast Chicken",
"restaurantName": "Kentucky\"s Fried Chicken",
"price": "550",
"rating": "4.8",
"totalRatings": "1000",
"image": "assets/images/Rectangle 17323 (2).png",
"isFavourite": false
},
{
"id": "5",
"name": "Ice Cream",
"restaurantName": "Naturals",
"price": "80",
"rating": "5.0",
"totalRatings": "1500",
"image": "assets/images/Rectangle 17324 (2).png",
"isFavourite": false
},
{
"id": "6",
"name": "Chicken Tandoor Combo",
"restaurantName": "Tandoori House",
"price": "455",
"rating": "4.3",
"totalRatings": "154",
"image": "assets/images/Rectangle 17323.png",
"isFavourite": false
},
{
"id": "7",
"name": "Pan Cake",
"restaurantName": "The Pancake Centre",
"price": "250",
"rating": "4.7",
"totalRatings": "256",
"image": "assets/images/Rectangle 17324.png",
"isFavourite": false
},
{
"id": "8",
"name": "Salad",
"restaurantName": "The Pancake House",
"price": "180",
"rating": "4.1",
"totalRatings": "203",
"image": "assets/images/Rectangle 17325.png",
"isFavourite": false
},
{
"id": "9",
"name": "Roast Chicken",
"restaurantName": "Kentucky\"s Fried Chicken",
"price": "550",
"rating": "4.8",
"totalRatings": "1000",
"image": "assets/images/Rectangle 17323 (2).png",
"isFavourite": false
},
{
"id": "10",
"name": "Ice Cream",
"restaurantName": "Naturals",
"price": "80",
"rating": "5.0",
"totalRatings": "1500",
"image": "assets/images/Rectangle 17324 (2).png",
"isFavourite": false
}
]
};
Map<String, dynamic> get popularDishes {
return {..._popularDishes};
}
Map<String, dynamic> getProductById(String id) { //The filter method that I've tried to write that yields the error
return _popularDishes["data"].where((value) => value.id == id).toList();
}
This is how I'm calling the getProductById method using provider.
routes['id']
is basically the id taken as a route argument from the previous page. The id is derived from the same JSON data that is on this question.
class CartScreenState extends State<CartScreen> {
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
final textScale = MediaQuery.of(context).textScaleFactor * 1.2;
final routes =
ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
routes['id']
final id = routes['id'];
final provider =
Provider.of<PopularDishesProvider>(context).getProductById(id);
CodePudding user response:
Map<String, dynamic> getProductById(String id) { //The filter method that I've tried to write that yields the error
return _popularDishes["data"].where((value) => value.id == id).toList();
}
First of all, you are accessing id as a getter on the map object so you have to write it like this
return _popularDishes["data"].where((value) => value['id'] == id).toList();
The second thing is your function return type is Map<String, dynamic>
but you are returning list as you have used toList()
so either make your function return type as List<Map<String, dynamic>>
or if you have to return only first single match then you can use firstWhere
instead of where
CodePudding user response:
A possible solution could be the following:
import 'package:collection/collection.dart';
Map<String, dynamic>? getProductById(String id) {
final dishes = _popularDishes["data"] as List<Map<String, dynamic>>;
return dishes.where((dish) => dish["id"] == id).firstOrNull;
}
By type casting your dishes list, you can make clear that you are dealing with maps of a certain type (like Map<String, dynamic>
). That way you can access a certain value by its key using square brackets (dish["id"]
) and then compare the value to the passed parameter.
Additionally, you tried to return a list (by using the toList()
method) but your return type was Map<String, dynamic>
. So if you would like to return a list, you could change the return type to List<Map<String, dynamic>>
. Otherwise you can use firstOrNull
(from the collection package) to get your result (or null if nothing was found). For returning null, you must mark the return type nullable.
Hope this solves the problem :)