Reputation: 807
In my flutter app I have a class and a list of classes like the following:
class GuestType {
final String name;
bool isActive;
GuestType({this.name, this.isActive});
}
List<GuestType> _guestTypes = [
GuestType(name: 'White', isActive: false),
GuestType(name: 'Blue', isActive: false),
GuestType(name: 'Lavander', isActive: false),
GuestType(name: 'Green', isActive: false),
GuestType(name: 'Pink', isActive: false),
GuestType(name: 'Yellow', isActive: false)
];
I'm mapping through _guestTypes and creating a card containing the name instance. Each card has the onPress attribute and what I need to achieve is that when a card is pressed, the isActive instance is set to true. However, only one card can be true at any time, so when a card is pressed all the other cards must be set to false.
This is my code to achieve the desired result:
...
children: _guestTypes
.map(
(type) => Card(
colour: type.isActive == true
? widgetAttivo
: widgetInattivo,
onPress: () {
setState(() {
_guestTypes
.map((guest) => guest.isActive == true
? setState(() {
guest.isActive = false;
type.isActive = !type.isActive;
})
: setState(() {
type.isActive = !type.isActive;
}));
});
},
...
This code doesn't work, I can still select and activate multiple cards.
Any clue?
Thanks a lot.
Upvotes: 0
Views: 402
Reputation: 77304
You are using the wrong tool for the job. map
is a way to create a new iterable, by mapping each item to a new item. That is not what you want. You simply want to iterate the existing items. That has always been a job for a loop:
onPress: () {
setState(() {
for(var guest in _guestTypes) {
guest.isActive = false;
type.isActive = !type.isActive;
}
}
}
I also shortened your loop body. It does the same thing, but with half the code.
Upvotes: 1
Reputation: 2862
Using map
and changing some attributes inside the callback will not affect you current list (This is why map returns Iterable
).
So as a solution I will propose the following :
setState(() {
_guestTypes = _guestTypes.map((guest) {
if(guest.name == type.name){
guest.isActive = true;
}else{
guest.isActive = false;
}
return guest;
}).toList();
});
You have to check if the selected item name is the same with the item in the map. make it isActive true and all the others false.
Upvotes: 1
Reputation: 21694
In your setState
call, you are re-mapping _guestTypes
, but are not doing anything with the return value. map()
does not map in-place, it returns an updated map.
Also, you don't need to use setState
both inside and outside the map function, only setting it around the content you want to update is enough (and better).
() {
setState(() {
// notice the change here - use the result and set the value in the state
_guestTypes = _guestTypes
.map((guest) {
// set `true` for same guest type, `false` for others.
// (use a different condition to compare them if that isn't good enough)
guest.isActive = type.name == guest.name;
// needs to return the final value for each item
return guest;
}).toList();
});
},
Upvotes: 1