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');
Related
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 have a mixed list of text and images and I would like to place the applicable text and image together on one card. The current code works for text however, when I try to add the image I always get an error. Does anyone know how to do this?
Any help is appreciated!
class Episode {
String seasonEpisode;
String airDate;
Image epImage;
Episode({this.seasonEpisode, this.airDate, this.epImage});
}
class EpisodeList extends StatefulWidget {
/*final Episode episodes;*/
#override
_EpisodeListState createState() => _EpisodeListState();
}
class _EpisodeListState extends State<EpisodeList> {
List<Episode> episodes = [
Episode(seasonEpisode: 'S24:E1', airDate: 'February 18, 2020', epImage: Image.asset('assets/Bachelor1.jpeg')),
Episode(seasonEpisode: 'S24:E2', airDate: 'February 25, 2020', epImage: Image.asset('assets/Bachelor1.jpeg')),
Episode(seasonEpisode: 'S24:E3', airDate: 'February 31, 2020', epImage: Image.asset('assets/Bachelor1.jpeg')),
];
Widget epCardTemplate(episode) {
return Card(
margin: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(episode.epImage),
Text(
episode.seasonEpisode
),
SizedBox(height: 6.0),
Text(
episode.airDate
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: DARK_GREY_COLOR,
body: Column(
children: episodes.map((episode) => epCardTemplate(episode)).toList(),
)
);
}
}
So what you are doing in your code is equivalent to
children: <Widget>[
Image.asset(Image.asset('assets/......')),
Text(
episode.seasonEpisode
),
SizedBox(height: 6.0),
Text(
episode.airDate
),
],
Basically, you are putting an image inside another image widget.
I am trying to copy values of one list to another,
I use three buttons 1st one to append a value to mylist, second one to clear the mylist, 3rd button to copy values from mynewlist to mylist.
i tried this
List<String> mylist = [
'Albania',
'Andorra',
'Armenia',
'Austria',
'Azerbaijan',
'Belarus',
'Belgium',
'Albania',
'Andorra',
'Armenia',
'Austria',
'Azerbaijan',
'Belarus',
'Belgium',
];
List<String> mynewlist = [
'Albania',
'Andorra',
'Armenia',
'Austria',
'Azerbaijan',
'Belarus',
'Belgium',
'Albania',
'Andorra',
'Armenia',
'Austria',
'Azerbaijan',
'Belarus',
'Belgium',
];
Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
print('clicked 1st');
print(mylist.length);
print(mynewlist.length);
mylist.add('sdsds');
});
},
child: Container(
child: Column(
children: <Widget>[
Image.asset(
'images/bulb.png',
width: 100,
height: 100,
),
Text('bulb')
],
),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
print('clicked 2nd');
print(mylist.length);
print(mynewlist.length);
//after i set mylist = mynewlist; when i click this button it clears the old and new list.
mylist.removeRange(0, mylist.length);
});
},
child: Container(
child: Column(
children: <Widget>[
Image.asset(
'images/bulb.png',
width: 100,
height: 100,
),
Text('bulb')
],
),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
print('clicked 3rd');
print(mylist.length);
print(mynewlist.length);
mylist = mynewlist;
});
},
child: Container(
child: Column(
children: <Widget>[
Image.asset(
'images/bulb.png',
width: 100,
height: 100,
),
Text('bulb')
],
),
),
),
),
],
),
)
On the initial time it works perfectly the second time i click the second button it clears the mylist and mynewlist.
How can i copy the values of second list without clearing the new new list
Use myList = List.from(mynewlist); instead of mylist = mynewlist;
Thats because you copied the object references (mylist = mynewlist) and not the content of the list. So after the first click, mylist has a reference to the same object in memory as mynewlist. So any operation on one of them, affect both.
To solve your problem you need to keep the object references intact and just copy around the contents of these lists.
var YOURCOPY = YOURLIST.map((v) => v).toList();
use:
myNewList = [...myOldList]
it creates a shallow copy of items from myOldList to myNewList
for more information: you can search for 'spread operator in dart'.
You can also call method:toList() on any iterables (in this case List) which you want to create a copy of and not a reference.
Deep copy of a custom class List
If you have a list of classes, make sure to clone/copy each class. Otherwise, if you change objects in the original list, it will also change in the new one.
Here is one way to prevent it:
Add a clone() function to your class
class RandomObject {
RandomObject(this.x, this.y);
//add clone function to your class:
RandomObject.clone(RandomObject randomObject): this(randomObject.x, randomObject.y);
int x;
int y;
}
To copy, map through each element and clone it
final List<RandomObject> original = [RandomObject(1, 2), RandomObject(3, 4)];
final List<RandomObject> copy = original.map((v) => RandomObject.clone(v)).toList();
I have a hardcoded list that I want to map it to a list of widgets. The code below shows squiggly lines with the error The return type 'List<ItemWidget>' isn't a 'Widget', as defined by anonymous closure.dart(return_of_invalid_type_from_closure).
.................MISSING CODE....................
ListView.builder(
itemBuilder: (context, index) => items.map((item) => ItemWidget(item: item)).toList();
)
..................MISSING CODE....................
class ItemWidget extends StatelessWidget{
final Item item;
ItemWidget({this.item});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: FittedBox(
fit: BoxFit.fill,
child: Image.asset(item.iconPath)
)
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Text(item.name),
)
],
);
}
}
EDIT:
This is the list of items, currently I hold just an item for testing purposes.
List<Item> items = [
Item(name: 'Medicines', iconPath: '$ICON_BASE_PATH/medicines.svg'),
];
If you have any idea please let me know, thanks!
The issues is using the ListView.builder, the builder function expects you to return one Widget at a time corresponding to the index provided. Use ListView directly instead.
Example:
ListView(
children: items.map((item) => ItemWidget(item: item)).toList(),
);
Hope that helps!
If you want to use ListView.builder then you can use as following. This may helps you.
body: ListView.builder(
itemCount: items == null ? 0 : items.length,
itemBuilder: (BuildContext context, int index) {
return ItemWidget(
item: items[index],
);
},
),
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!