I have this data as json:
{
"id":1,
"value":"value x",
"option":{
"id":1,
"name":"option d"
},
"attachment":null,
"price":0
},
{
"id":2,
"value":"value y",
"option":{
"id":1,
"name":"option b"
},
"attachment":null,
"price":0
},
I wanted to view them as ListView after grouping them with Option.name so the return is a map as:
Map<String, List<Option>> getGrouped(
List<Option> options) {
Map<String, List<Option>> groupByData = groupBy(
itemVariations, (obj) => (obj as Option).option.name);
return groupByData;
}
I am not how can this be viewed as a nested Text() widget? I tried many things and its always:
The argument type 'List<Option>' can't be assigned to the parameter type 'String'.
You can try this: var data = { "key1": "value1", "key2": "value2", "key3": "value3", }; var myMap = Map<String, dynamic>. from(data); print(myMap); With dynamic in Map<String, dynamic> we can have the values of the map of any type.
forEach() Function. Applies the specified function on every Map entry. In other words, forEach enables iterating through the Map's entries.
I'll answer the question as posed first, however I wanted to put forward a different way of approaching this problem:
In order to iterate through a map, you have to get the map keys, and then iterate through the keys, using them to access the map. Here's an example:
Map<String,String> testMap = {"first":"1st","second":"2nd", "third":"3rd"};
main(){
for (String key in testMap.keys){
print(key);
print(testMap[key]);
}
}
here's a dartpad with the above example: https://dartpad.dev/8c342ae34d34b5572795a4b8bc60e1b6
However, I'm guessing that you don't need to do that.
But first, some information.
In your comments, I asked what you were defining 'option' as. The reason I asked this is because you put List in your code. The <> denotes a variable type, not a Map key. Also, capital letters in Dart are considered class names. Therefore, when I read your code, I assumed that you had done something like this:
class MyOption { //<-- this defines the class MyOption
final int id;
final String name;
}
MyOption ex1 = MyOption(1, "option a"); // <-- these define objects ex1, ex2
MyOption ex2 = MyOption(2, "option b"); // <-- you can defined these as 'MyOption'
// types because you defined the
// MyOption class.
List<MyOption> myList = [ex1,ex2]; // this is a list of Option object.
so, the reason that you are getting the "argument type List can't be assigned to the parameter 'string' is because you're mixing types of variable. (specifically String and List)
Second, it's hard to tell, but I'm not convinced that you are handling the decoded json. You need to do this before you start manipulating it in flutter. In order to do that you need to do something like this:
var jsonStr = """ // <-- the json data you get should look like this:
{
"results": [
{
"id":1,
"value":"value x",
"option":{
"id":1,
"name":"option d"
},
"attachment":null,
"price":0
},
{
"id":2,
"value":"value y",
"option":{
"id":1,
"name":"option b"
},
"attachment":null,
"price":0
}
]
}
""";
main() {
Map<String, dynamic> myMap = jsonDecode(jsonStr); // decode json here
And therefore, we can iterate through the array in the normal way
print("Values from json data:");
for(int i=0; i<myMap['results'].length; i++){
print(myArray[i]['option']['name']);
}
}
I made a dartpad with this 2nd set of code so you can play around with it:
https://dartpad.dev/7f670e3835ad292f2b325dd3d40bb41c
Please let me know if this helps, and I'll update my answer with anything I'm missing
this is a working code. It prints a ListView by option name like this:
I hope it can help you:
import 'package:flutter/material.dart';
import "dart:convert";
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
static String json = """[{
"id":1,
"value":"value x",
"option":{
"id":1,
"name":"option d"
},
"attachment":"a",
"price":0
},
{
"id":2,
"value":"value y",
"option":{
"id":1,
"name":"option b"
},
"attachment":"b",
"price":0
},
{
"id":3,
"value":"value z",
"option":{
"id":1,
"name":"option b"
},
"attachment":"b",
"price":0
},
{
"id":3,
"value":"value h",
"option":{
"id":1,
"name":"option b"
},
"attachment":"b",
"price":0
}]""";
@override
Widget build(BuildContext context) {
List<Options> list = List<Options>.from(
jsonDecode(json).map((x) => Options.fromJson(x))
);
Map<String, List<Options>> mymap = Map<String, List<Options>>();
list.forEach((option){
print(option.option.name);
if (!mymap.containsKey(option.option.name)) {
mymap[option.option.name] = List<Options>();
}
mymap[option.option.name].add(option);
});
print(mymap.keys.length);
return Scaffold(
body: Container(
child: ListView.builder(
itemCount: mymap.length,
itemBuilder:
(_, index) {
String key = mymap.keys.toList()[index];
return Text("$key ${mymap[key].map((o)=>o.value)}");
}
),),
);
}
}
class Options {
final int id;
final String value;
final Option option;
final dynamic attachment;
final int price;
Options({
@required this.id,
@required this.value,
@required this.option,
@required this.attachment,
@required this.price,
});
factory Options.fromJson(Map<String, dynamic> json) => Options(
id: json["id"],
value: json["value"],
option: Option.fromJson(json["option"]),
attachment: json["attachment"],
price: json["price"],
);
Map<String, dynamic> toJson() => {
"id": id,
"value": value,
"option": option.toJson(),
"attachment": attachment,
"price": price,
};
}
class Option {
final int id;
final String name;
Option({
@required this.id,
@required this.name,
});
factory Option.fromJson(Map<String, dynamic> json) => Option(
id: json["id"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With