Flutter: DropDownMenuItem - How to access i or index - flutter

I am trying to access my counter variable i OR the current index of the current item, but it seems impossible.
items: listeZutatenDropdown[i].map((String value) {
return DropdownMenuItem(
value: value,
child: (value == "Zutat auswählen") ? new Text("Zutat auswählen") : new Text(value + " " + i.toString()),
);
}).toList()
If I print i out as I do in my code example, I always get 0. (does that have to do with the scope of the return statement?).
If I try to use index as additional parameter, I get "The argument type 'List' can't be assigned to the parameter type 'List<DropdownMenuItem>?'" and "The argument type 'List' can't be assigned to the parameter type 'List<DropdownMenuItem>?'.dart(argument_type_not_assignable)
The argument type 'DropdownMenuItem Function(int, String)' can't be assigned to the parameter type 'dynamic Function(String)'" which confuses me because I see people using the .map() method as well as the .forEach() method all the time, but when I want to use them....^^
Lastly, I tried to save i in a variable and to access this variable in my return statement. Same outcome as before (0).
Hope you can tell me what I am doing wrong! Looking forward to your feedback!
Regards
Thomas

Since I was not able to access my counter variable nor the index, I just copied the code I already had for my listZutatenDropdown
listeZutatenDropdown = List<List<String>>.generate(listZutaten.length, (i) => List<String>.generate(listZutaten.length, (i) => listZutaten[i]));
and added the list of units
listeZutatenUndEinheiten = List<List<String>>.generate(listZutaten.length, (i) => List<String>.generate(listZutaten.length, (i) => listZutaten[i] + " (" + listEinheiten[i] + ")"));
Not the cleanest way in my opinion, because I would prefer to go with the counter variable OR the index to reduance unnecessary code, but it works.

Related

flutter null safety from prefs.setStringList -> error : the argument list<String?> can't be assigned to the parameter type List <String>

Hello I try to make null safety migration, but have a probleme with
prefs.setStringList("save_list_autre2",save_list.toList());
the error is : the argument list<String?> can't be assigned to the parameter type List
RegExp regExp = new RegExp(r'(...)');
var save_list= regExp.allMatches(decrypted).map((z) => z.group(0));
if(regExp.allMatches(decrypted)==null ){
[...]
} else {
prefs.setStringList("save_list_autre2",save_list.toList());
}
I add .toString() from save_list= regExp.allMatches(decrypted).map((z) => z.group(0).toString());
the error is removed but I don't know if it's the good solution
When you call z.group(0) the group method could return null if there was no group with the given index (0 in this case). so dart thinks you might have some null values on your list of strings.
The reality is that you shouldn't get any null values because you are passing a 0. So to tell dart that the method isn't returning null, use the ! operator:
regExp.allMatches(decrypted)
.map((z) => z.group(0)!)
If, by some chance, you happened to have any null values, this code will not work (as I said, I believe you won't but what do I know? I've never used regexes with dart)
If that's the case, you first need to filter the null values and then use the !:
regExp.allMatches(decrypted)
.map((z) => z.group(0))
.where((v) => v != null) // filter out null values
.map((v) => v!); // let dart know you don't have any null values.
Hopefully that's enough to fix the problem

Confusion with Null safety

I'm pretty new to flutter and because of the null safety feature I've been getting a lot of errors from a code that will run perfectly fine in Java or other langs. For example this-
int ? i;
var icecreamFlavours = ['chocolate', 'vanilla', 'orange'];
icecreamFlavours.forEach((item) {
i++; //This is where I get the error
print('We have the $item flavour');
});
My Error Message
Error: Operator '+' cannot be called on 'int?' because it is potentially null.
i++;
Error: A value of type 'num' can't be assigned to a variable of type 'int?'.
i++;
You can't do either i++ or i+=1 on a nullable variable, because the reason is simple, null variable can have null values which will make increment no sense.
In addition to this, you can't even do i!++ or i!+=1 even if you are sure that i is not null. There is an open issue for this https://github.com/dart-lang/language/issues/1113
So for now you can do this i = i! + 1
Update:
For i = i! + 1 to work you need to be sure about i not being null. So it's better to initialise/assign i with some value before using it.

Flutter GetX can't assign Set<CustomClass> to RxSet<CustomClass>

I am developing an application and came across a problem, which does not cause an error but pretty frustrating for me.
The situation is that I have an RxSet of CustomClass objects with default initialization to empty Set. When I fetch data from the server, I want to assign the result to this set. As GetX suggests, I should go like myRxSet = dataFetchedFromServer. This gives me a compile time error. myRxSet.value = dataFetchedFromServer still works, but gives an info that I should not assign to .value property.
A sample code can be seen bellow
RxSet<MyCustomClass> myCustomClassEntries = Set<MyCustomClass>().obs;
Future<void> syncData() async {
myCustomClassEntries = await _fetchDataFromServer(); // this gives me compile time error
myCustomClassEntries.value = await _ fetchDataFromServer(); // this gives me a warning that RxSet is not intented to be used this way.
}
GetX version: ^4.3.4
Flutter version: 2.2.3
Dart version: 2.13.4
Any idea what I'm doing wrong?
Edit
_fetchDataFromServer() does not matter in this situation, just wanted to give some context to the problem. As simple as it is:
RxSet<MyCustomClass> myCustomClassEntries = Set<MyCustomClass>().obs;
// This line gives me a compile time error. It says Set<MyCustomClass> can't be assigned to RxSet<MyCustomClass>
myCustomClassEntries = new Set<MyCustomClass>();
// This line works, just like everywhere else with GetX, but says .value is no longer intented to be used on RxList, RxSet or RxMap. It recommends to use the syntax above, which gives the error.
myCustomClassEntries.value = new Set<MyCustomClass();
From GetX changelog
Change: You do not need to access the ".value" property of primitives. For Strings you need interpolation. For num, int, double, you will have the normal operators, and use it as dart types. This way, .value can be used exclusively in ModelClasses. Example:
var name = "Jonny" .obs;
// usage:
Text ("$name");
var count = 0.obs;
// usage:
increment() => count ++;
Text("$count");
Thus: List, Map, Set, num, int, double and String, as of this release, will no longer use the .value property.
NOTE: The changes were not break changes, however, you may have missed the details of the documentation, so if you faced the message: "The member 'value' can only be used within instance members of subclasses of 'rx_list.dart' "you just need to remove the" .value "property from your list, and everything will work as planned. The same goes for Maps and Sets.
In short, when using a list in Getx, you don't need to use .value.
...
myCustomClassEntries = Set<MyCustomClass>().obs; // just add .obs and treat it like a regular list.
final object = MyCustomClass();
myCustomClassEntries.add(object); // no error here and not using .value
I asked for the _fetchDataFromServer() function because it matters in the sense of what you're trying to return. But regardless, return an observable Set<MyCustomClass>() and then you won't have type casting errors.
Update after follow up questions:
Just return an RxSet<MyCustomClass> from your _fetchDataFromServer function so you have matching types.
Future<RxSet<MyCustomClass>> _fetchDataFromServer() async {
final tempList = Set<MyCustomClass>().obs;
// ... your code that populates list from server
return tempList;
}
You don't need to clear the list. Below will update myCustomClassEntries with only what is returned from the function.
myCustomClassEntries = await _fetchDataFromServer();
I used them on marker class for google map,markers were not setting after getting current location:
RxSet<Marker> markers = <Marker>{}.obs;
Obx(()=>
GoogleMap(
zoomControlsEnabled: true,
compassEnabled: false,
myLocationButtonEnabled: false,
onMapCreated: (GoogleMapController controller) {
},
markers: vm.markers.value,
),
)

How to get previous vals in Yup validation

I would like to validate a list of items(strings) and make sure there isn't a duplication(if there is, show error message) when user tries to modify the item. However, if the user try to modify it and finally keep the same value, we don't show the error message. In validation, I have something like below for each field in the array. In the function inside test below, I can only get current modified value as parameter - value, but not previous value so I cannot do validation with previous value. I would like to know if there is a way to get previous value(i.e. value before any change) for the value currently been modified? If there is only one value in the list, it is easy, but if there are multiples, it is hard to track.
Yup.object().shape({
rows: Yup.array(
Yup.lazy(() => (
myObject.test('field', 'error message', function (value) { ... } )
)
)
)
})

Get value from Instance in Flutter

I am making a search request on the List with the Provider pattern.
List<Device> _devices = [
Device(one: 'Apple', two: 'iphone'),
Device(one: 'Samsung', two: 'Galaxy')
];
And Query is like this
List<Device> queryQuery(String value) {
return _devices
.where((device) => device.one.toLowerCase().contains(value.toLowerCase()))
.toList();
the result I expect to get is iphone when I passed the value Apple.
But the result on the screen that I got is [instance of ‘Device’]
when I code like this
child: Text('${deviceData.getDevice('Apple')}'
I do know I should be using some kind of key using two... but I have no idea :-(
You serialized the wrong object.
What you did end-up being similar to:
Text(Device(one: 'Apple', two: 'iphone').toString());
But you don't want to do Device.toString(). What you want instead is to pass Device.two to your Text.
As such your end result is:
Text('${chordData.chordExpand('Apple').two}')
By the look of [Instance of 'Device'], it seems the function is returning a list so it is a good idea to check if the list is empty or not. if it is not empty, one of the elements is still needed to be selected. I guess it should be Text('${chordData.chordExpand('Apple')[0].two}') in case the list is not empty.
To summarize, use something like this to handle the case when list is empty
// Inside your build method before returning the widget
var l = chordData.chordExpand('Apple'); // Returns a list of devices
String textToWrite; // Here we will store the text that needs to be written
if(l.isEmpty) textToWrite = 'No results'; // If the filter resulted in an empty list
else textToWrite = l[0].two; // l[0] is an instance of a device which has a property called two. You can select any instance from the list provided it exists
return <Your Widget>(
.....
Text(textToWrite),
.....
);