My function types() should return a unique list of ExpansionTiles.
In dart combining .toSet().toList() is really efficient in removing duplicates in List and I am trying to do the same here but I'm still rendering duplicates.
In the picture I don't want NISSAN to appear twice, just once as one category.
types() {
return snapshot.data.documents.map((doc) {
if(doc['car']['registryNumber'] != null && doc['car']['category'] ==
'car') {
return ExpansionTile(
title: new Row(
children: <Widget>[
new Text(
doc['car']['type'].split(' ')[0],
style: new TextStyle(
fontSize: 15.0
),
)
],
),
children: <Widget>[
],
);
} else {
return new Text('');
}
}).toSet().toList();
}
Don't forget to add a unique key: to ExpansionTile to avoid any duplicate issues!
Related
I have a function that receives a list in the function parameter and I am displaying that list.
I have a validation in the Text, when it is null it shows me a message that says "no data" or otherwise it shows me the value of the list.
What I want to remove the cancel icon when it is null and only appear when I have a value to display.
Help would be greatly appreciated.
Code and Image ::
Widget SfuluilderSuggestions(List <SDM> historialMenuPrincipal){
return Container(
child:StatefulBuilder(
builder:(context,setState)
{
return Container(
child: ListView.builder(
itemCount: historialMenuPrincipal.length,
itemBuilder: (context,i)
{
contentPadding: EdgeInsets.symmetric(vertical: 12,horizontal: 16);
leading:CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(
"https://2.bp.blogspot.com/-3ZzNt8ZjQk/WR9W4Fn4II/AAAAAAAJw/_inTVynhS6V75IZ-461-pda7WyrTStwCEw/s1600/A.jpg"),
);
return
ListTile(
title: Text(historialMenuPrincipal[i] == null ? "no data":historialMenuPrincipal[i].email ),
trailing: IconButton(
icon: Icon(Icons.cancel,color: Colors.black,),
onPressed: () {
setState(() {
historialMenuPrincipal.remove(historialMenuPrincipal[i]);
});
},
),
);
}
),
);
}
)
);
}
You can check if the text is null -
trailing: Text(historialMenuPrincipal[i] != null ? IconButton(
icon: Icon(Icons.cancel,color: Colors.black,),
onPressed: () {
setState(() {
historialMenuPrincipal.remove(historialMenuPrincipal[i]);
});
},
) : Padding(padding:EdgeInsets.zero),
While historialMenuPrincipal contains data, you can remove only when data is available. You can pass null on trailing.
trailing:
historialMenuPrincipal.contains(historialMenuPrincipal[i])
? IconButton(...)
: null
If you want to skip the generating ListTile, you can check on return level and provide SizedBox or better filter data while generating the list.
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;
},
);
}
The idea behind my code is to populate a Column widget with dynamic data I get from a list of objects
I use a List>> that's essentially just a list of objects.
My List :
List<List<Map<String, String>>> listCardsAll = [
[
{
"cardCate": "AMEX",
"cardDesc": "American Platinum 6",
"cardImg":
"images/AMEX/American-Express®-Green-Card-Earn-Rewards-Points.png"
}
],
[
{
"cardCate": "AMEX",
"cardDesc": "American Platinum 5",
"cardImg":
"images/AMEX/American-Express®-Green-Card-Earn-Rewards-Points.png"
}
],
];
Then I call a function within a column that returns a Widget(I want to return a List but it gives an error)
Widget:
Column(
children: <Widget>[
Row(
children: <Widget>[generateCardsALL()],
)
],
)
I Use a for-loop then in the function a make a widget with that dynamic data but it only returns one widget rather than the Collection that i was hoping for.
my Function :
Widget generateCardsALL() {
var count = 0;
for (var item in listCardsAll) {
count++;
if (count <= 2) {
return ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: count,
);
} else {
count = 0;
return ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: 3,
);
}
}
}
(The cardRowNum is only to see when its 3 cards next to each other that it can generate a new row)
This is the ReusableCards
ReusableCards:
class ReusableCards extends StatelessWidget {
final String cardLink;
final int cardRowNum;
final String cardName;
ReusableCards(
{#required this.cardLink,
#required this.cardRowNum,
#required this.cardName});
#override
Widget build(BuildContext context) {
// addToListcards(cardLink);
print("Inserted");
return (cardRowNum == 1 || cardRowNum == 2
? GestureDetector(
onDoubleTap: () {},
child: Padding(
padding: EdgeInsets.fromLTRB(0, 15, 15, 20),
child: Container(
width: MediaQuery.of(context).size.width * 0.24,
child: SizedBox(
child: Column(
children: <Widget>[
Image.asset(cardLink, fit: BoxFit.fill),
Text(cardName)
],
),
),
),
),
)
: cardRowNum == 3
? Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 20),
child: Container(
width: MediaQuery.of(context).size.width * 0.24,
child: SizedBox(
child: Column(
children: <Widget>[
Image.asset(cardLink, fit: BoxFit.fill),
Text("" + cardRowNum.toString())
],
),
),
),
)
: SizedBox());
}
}
if I want to make it a List rather then just a widget it breaks. Can someone please help me with this dilemma
Try using map for iterating through the list and getting a list of widgets,
Example:
Column(
children: listCardsAll.map((oneCard){
return Container(
child: Text(oneCard.cardDesc)
);
}).toList(),
)
I think the problem is that inside of the function generateCardsALL. You don't return an array of Widgets, you should change to this.
List<Widget> generateCardsALL() {
var count = 0;
List<Widget> widgets;
for (var item in listCardsAll) {
count++;
if (count <= 2) {
widgets.add(ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: count,
));
} else {
count = 0;
widgets.add(ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: 3,
));
}
}
return widgets;
}
I hope this meet all flutter developers well.
i'm working on an app and there are several issues i've been going through. here is my question.
i want to switch between selectedLocations and it will bring out forms related to the location out for users to fill.
here are the locations below in pictures and the codes follows.
void switchSelectedCountry(selection) {
events = selection;
scoops = selection;
setState(() {
_selectedLocation = selection;
});
}
formField: FixDropdownButtonFormField(
value: _selectedLocation,
hint: Text('Select'),
items: <String>['Scoops', 'Events',].map((String value) {
return new FixDropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
onChanged: (newValue) {
setState(() {
_selectedLocation = newValue;
});
},
),
),
you can check which value has been selected in drop down and based on that you can show specific form,
for example,
if(dropdownValue == 'events') Column(
children: <Widget>[
TextFormField(
controller: yearController,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).translate(
'year'),
hintStyle: TextStyle(fontSize: 10),
filled: true,
),
keyboardType: TextInputType.number,
),
],
),
if(dropdownValue == 'Scoops') Sizebox(RETURN YOU WIDGET)