I'm creating an flutter app which should show list of teams, and each team is an object with items like
name: string
players: array of
name: string
so it looks like this
List teams = [
{
'name': 'Team one',
'players': [
{
'name': 'Team one player one',
},
{
'name': 'Team one player two',
},
{
'name': 'Team one player three',
},
]
},
{
'name': 'Team two',
'players': [
{
'name': 'Team two player one',
},
{
'name': 'Team two player one',
},
{
'name': 'Team two player three',
},
]
},
];
Further, in my code, I'm iterating through all teams with ListView, like this
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: renderTeams(teams),
),
);
}
and renderTeams() looks like this:
Widget renderTeams(List teams) {
return ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
Text(teams[index]['name']),
Row(
children: <Widget>[
Flexible(
child: PlayerCard(
player: teams[index]['players'][0],
),
),
Flexible(
child: PlayerCard(
player: teams[index]['players'][1],
),
),
Flexible(
child: PlayerCard(
player: teams[index]['players'][2],
),
),
],
)
],
),
);
},
);
}
This works well, everything gets rendered accordingly.
However, I'd like to, instead adding each player separately, iterate through each's team players, so my renderTeams() would look like this:
Widget renderTeams(List teams) {
return ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
Text(teams[index]['name']),
renderPlayers(teams[index]['players'])
],
),
);
},
);
}
and renderPlayers() looks like this:
renderPlayers(players) {
return Row(children: players.map((player) => {
Flexible(
child: PlayerCard(
player: player,
),
)
}).toList());
}
This is where my troubles begin, as I'm getting errors like
type 'List<dynamic>' is not a subtype of type 'List<Widget>'
And I've googled around, but other responses, tried to fix types, but that leads me into infinite loop of trying to fix errors i do not understand.
Anyone got any hint? Thanks in advance
Remove { }
renderPlayers(players) {
return Row(children: players.map((player) =>
Flexible(
child: PlayerCard(
player: player,
),
)
).toList());
}
Explanation
=> means return. => { ... } means returning a function (dynamic). That's why it was detected as List<dynamic>
Use Spread Operator [...]
The best solution for this type of problem is the Spreed Operator [...]. The spread operator combines two or more list instances. It also extends a collection's elements of a such as a list.
You can use it with Columns, Rows or Listview.
Like this:
// List
final variableValuesList = [
VariablesWithValues(
title: 'a',
value: 1,
),
VariablesWithValues(
title: 'b',
value: 1,
),
];
/// using inside column
Column(
children: [
///getting values from the list through spread operator
...variableValuesList.map((item) => Text(${item.title} = ${item.value})
).toList(),
Related
I have a json list. from this i want to delete a particular item. Below is my code.
final List _vehicleList = [
{
'vehicleNumber': 'KL-14-V-5208',
'vehicleType': 'Two Wheeler',
},
{
'vehicleNumber': 'KL-13-H-8880',
'vehicleType': 'Four Wheeler',
},
{
'vehicleNumber': 'KL-14-M-6889',
'vehicleType': 'Three Wheeler',
},
];
This is my list. Here from this i want to delete the item based on vehicleNumber when i press a delete button. I'am using listview builder. When i print the list after the button press nothing happens
This is my UI Code.
return Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
_vehicleList[index]['vehicleNumber'],
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
_vehicleList[index]['vehicleType'],
),
),
GestureDetector(
onTap: () {
print('Deleted');
_vehicleList.removeAt(_vehicleList[index]);
print(_vehicleList);
},
child: const Padding(
padding: EdgeInsets.all(12.0),
child: Icon(
FontAwesomeIcons.timesCircle,
color: Colors.redAccent,
),
),
),
],
);
You should change like this;
Before;
_vehicleList.removeAt(_vehicleList[index]);
after
_vehicleList.removeAt(index);
Documentation of how to use the "removeAt" method. https://api.flutter.dev/flutter/dart-core/List/removeAt.html
Try below code hope its help to you. just pass your index
_vehicleList.removeWhere((element) => element["vehicleNumber"] == 'KL-14-V-5208');
I'm trying to create a List of containers containing a Headline and multiple cards. It should look like this in the end:
The Scaffold should contain a List of containers containing Rows of Cards and Text.
I'm not sure if that's smart so if you have a recommendation how this could be done better...
This is my code so far (without text "Text 1" segments):
body: ListView(
children: getItems(snapshot),
),//getItems(snapshot),
);
}
getItems(AsyncSnapshot<List<html.Document>> snapshot) {
List<Container> containers = [];
for(int x = 0; x<snapshot.data!.length; x++) {
containers.add(toRow(snapshot.data![x]));
}
return containers;
}
/*
Build list of containers first in a Row -> cards....
*/
toRow(html.Document document){
return Row(
children: listofcards(document),
);
}
listofcards(html.Document document) {
List<Card> cards = [];
return FutureBuilder<List<tage>>(
future: SiteParser().getData(document),
builder: (BuildContext context, AsyncSnapshot<List<tage>> document) {
for(int q = 0; q<document.data!.length; q++) {
containers.add(_buildCard(document.data![q]));
}
return cards;
},
);
}
_buildCard(tage snap) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: MyThemes().choosecardcolor(snap),
elevation: 5,
//color: _chooseColor(snap.art.toString()),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(snap.stunde),
Text(snap.klasse),
Text(snap.raum)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(snap.art),
Text(snap.lehrer),
Text(snap.mitteilung)
],
)
],
),
);
}
At the moment I can't do that, because "The return type 'List' isn't a 'Widget', as required by the closure's context. ".
It was easier thanks to #ravindra-s-patil's recommendation to use group list view.
Here is my code I've wrote.
Widget buildrevresh(AsyncSnapshot<List<html.Document>> snapshot) {
return RefreshIndicator(
onRefresh: _refresh,
child: buildData(snapshot),
);
}
Widget buildData(AsyncSnapshot<List<html.Document>> snapshot) {
List<List<tage>> days = [];
for(int x = 0; x<snapshot.data!.length; x++) {
days.add(SiteParser().getData(snapshot.data![x]));
}
return GroupListView(
itemBuilder: (context, index) {
return _buildCard(days[index.section][index.index]);
},
sectionsCount: days.length ,
groupHeaderBuilder: (BuildContext context, int section) {
return Text(
days[section].first.datum,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600));
},
countOfItemInSection: (int section) {
return days[section].length;
},
);
}
I am trying to implement a search function in my app for filtering between many entries in a list of map.
The data structure that I have is:
[{Entry: Accident , Definition: An unexpected event or circumstance without deliberate intent.}, {Entry: Accident Insurance , Definition: Insurance for unforeseen bodily injury.}, {Entry: Accident Only , Definition: An insurance contract that provides coverage, singly or in combination, for death, dismemberment, disability, or hospital and medical care caused by or necessitated as a result of accident or specified kinds of accident.}, {Entry: Accident Only or AD&D , Definition: Policies providing coverage, singly or in combination, for death, dismemberment, disability, or hospital and medical care caused by or necessitated as a result of accident or specified kinds of accidents. Types of coverage include student accident, sports accident, travel accident, blanket accident, specific accident or accidental death and dismemberment (ad&d).} ... etc, etc. ]
These are the contents of the .json file:
[
{
"Entry": "Accident ",
"Definition": "An unexpected event or circumstance without deliberate intent."
},
{
"Entry": "Accident Insurance ",
"Definition": "Insurance for unforeseen bodily injury."
},
[... and looooots of many other "Entry", "Definition" pairs like these]
{
"Entry": "Written Premium ",
"Definition": "The contractually determined amount charged by the reporting entity to the policyholder for the effective period of the contract based on the expectation of risk, policy benefits, and expenses associated with the coverage provided by the terms of the insurance contract."
}
]
Each map entry creates one button with an associated definition.
The user is queried for a search query to get only the button(s) that satisfy the query result.
I include the .dart file that I am trying to implement:
import 'package:flutter/material.dart';
import 'listentries.dart';
import 'destination.dart';
import 'dart:convert';
// ignore: must_be_immutable
class searchScreen extends StatefulWidget {
final String searchTerm;
searchScreen({this.searchTerm});
#override
_SearchScreenState createState() => new _SearchScreenState();
}
class _SearchScreenState extends State<searchScreen> {
#override
Widget build(BuildContext context) {
final widgetElements = new ListEntries(); // From listentries.dart
var searchedItems =
widgetElements; // Copy from widgetElements filter out from here
var query;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(
"Search your term",
style: TextStyle(fontSize: 20),
),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (query) {
//search is done here
// filterSearchResults(query);
},
decoration: InputDecoration(
labelText: 'Search',
hintText: 'Search your term',
suffixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(25.0),
),
),
),
),
),
Expanded(
child: FutureBuilder(
future: DefaultAssetBundle.of(context)
.loadString('assets/data.json'),
builder: (context, snapshot) {
var entries = json.decode(snapshot.data.toString());
final item = entries.where((e) => e['Entry'] == 'Accident'); //Accident will be changed with query
print(item);
print(entries);
return ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
var entrada = entries[index];
//print(entrada);
return Container(
margin: EdgeInsets.symmetric(vertical: 2.0),
color: Colors.transparent,
width: MediaQuery.of(context).size.width,
height: 60,
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Destination(
entry: entrada['Entry'],
definition: entrada['Definition'],
),
),
);
},
color: Colors.blue[900],
child: Text(
entrada['Entry'],
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 18.0,
),
),
),
);
},
itemCount: entries == null ? 0 : entries.length,
);
},
),
//child: searchedItems,
),
],
),
),
);
}
}
The issue that I am seeing is that the filtered result (item) is empty and it should contain the entry related to "Accident".
Could you give a hand for the implementation of this search functionality?
Thanks in advance
add .toList() to create new list
final item = entries.where((e) => e['Entry'] == 'Accident').toList();
Here is a stripped down code sample describing how to filter the items:
final List<Map<String, String>> items = [
{'Entry': 'Accident', 'Definition': 'Accident description.'},
{'Entry': 'Accident Insurance', 'Definition': 'Insurance description.'},
];
void main() {
final results = items.where((item) => item['Entry'] == 'Accident');
print(results);
// Iterable<Map<String, String>> ({Entry: Accident, Definition: An unexpected event or circumstance without deliberate intent.})
final result = results.first;
print(result);
// Map<String, String> {Entry: Accident, Definition: An unexpected event or circumstance without deliberate intent.}
}
Note that where returns an Iterable. You can use toList() to get a List of Maps.
Here is a Flutter sample application closer to what you did before:
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: MyWidget()));
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString('assets/entries.json'),
builder: (context, snapshot) {
final items = json.decode(snapshot.data.toString());
final result =
items.where((item) => item['Entry'] == 'Accident').first;
return Column(
children: [
Text('Accident Definition:'),
Text(result['Definition']),
],
);
},
),
);
}
}
The JSON File I used is here:
[
{
"Entry": "Accident",
"Definition": "Accident description."
},
{
"Entry": "Accident Insurance",
"Definition": "Insurance description."
}
]
I am trying to create a list of switch tiles in flutter which have separators between the tiles.
I've tried doing this by using ListTile.divideTiles:
ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
SwitchListTile(
secondary: Icon(Icons.signal_cellular_4_bar),
title: Text(
"First Tile",
),
value: var1,
onChanged: (bool value) {
setState(
() {
var1= value;
},
);
},
),
SwitchListTile(
secondary: Icon(Icons.swap_vert),
title: Text(
"Second Tile",
),
value: var2,
onChanged: (bool value) {
setState(
() {
var2= value;
},
);
},
),
],
),
),
But when I tried running the code I got the following error:
"type '_SyncIterable<Widget>' is not a subtype of type 'List<Widget>'"
Who do I create a list of switch tiles with separator?
Please try this.
Add .toList() to the end of your ListTile.divideTiles
ListTile.divideTiles(
// all your code
// all your code
// all your code
).toList()
Why don't you try ListView.separated ?
int _selectedIndex = 0;
return ListView.separated(
//Here's your separator
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 10, //Whatever spacing you want.
);
},
physics: BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 2, //How many tiles you want
padding: EdgeInsets.all(10),
itemBuilder: (BuildContext context, int index) {
return ClipRRect( //round up the edges for nicer look
borderRadius: BorderRadius.all(Radius.circular(5)),
//And here's your tile
child: SwitchListTile(
tileColor: Colors.grey[900],
selectedTileColor: Colors.black,
selected: index == _selectedIndex,
value: ... ,
onChanged: (v) {
...
},
title: Text('Tile #' + index.toString()),
subtitle: Text('-'),
),
);
},
);
I'm trying to iterate through list to render multiple widgets. The list is setup so every item has 2 sub-properties, I'm trying to use the .map property to make this work.
I've tried this before with another project and it worked, but this time there's a change with the consistency of sub properties (certain numbers of the list have more that 2 sub-properties).
var storyMap = [
{
"story":
"Your car...",
"answer": [
["I'll hop...", 1],
["Better ask...", 1],
]
},
{
"story": "He nods...",
"answer": [
["At least...", 1],
["Wait, I...", 1],
]
},
{
"story":
"As you...",
"answer": [
["I love...", 1],
],
},
];
Widget build(BuildContext context) {
return CupertinoApp(
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
Column(
children: <Widget>[
...(storyMap[storyMapIndex]["answer"]
as List<Map<String, Object>>)
.map((number) {
return Column(
children: <Widget>[
CupertinoButton(
child: Text(number[1]),
onPressed: () {
setState(() {
storyMapIndex += number[2];
}); //return
},
),
], //<Widget>[]
); //Column
}).toList(),
], ////<Widget>[]
),
],
),
),
),
); //cupertino app
}
//better looking code file is in here
https://github.com/Pshah2023/Destini-App
I wanted this to iterate through every item in the list, look at sub properties and use it properly. This din't work and it gave the error
Object isn't a subtype of String.
Probably from the line with List> (but I can't change that line or it will iterate through the wrong items)