multidimensional list wont update state - flutter

how i can update my state in multidimensional list like screen. I can update state in first list level, but if i go on next level, state won't update
[0]:MegaFileModel (FileM(id: 714a55f4-d620-4fcb-a723-16af2c6115e3, fileName: Альбомы, extension: folder, preview: null, type: DIRECTORY, uploadUrl: null, serverfileName: null, addDate: 14.12.2021 09:04:14, checked: false))
addDate:"14.12.2021 09:04:14"
checked:false
content:List (3 items)
dir:Map (2 items)
extension:"folder"
fileName:"Альбомы"
id:"714a55f4-d620-4fcb-a723-16af2c6115e3"
preview:null
serverfileName:null
type:"DIRECTORY"
uploadUrl:null
hashCode:92220431
isDirectory:true
runtimeType:Type (MegaFileModel)
This is my function which i call every time when i want update state
List<MegaFileModel> getNewContentListState(List<MegaFileModel> state,
List<MegaFileModel> newState, bool value, String id) {
for (var i = 0; i < state.length; i++) {
if (state[i].id == id) {
newState.add(state[i].copyWith(checked: value, content: []));
} else {
newState.add(state[i].copyWith(content: []));
}
if (state[i].type == 'DIRECTORY') {
getNewContentListState(
state[i].content, newState[i].content, value, id);
}
}
return newState;
}
void doPick(bool value, String id) {
List<MegaFileModel> newState = [];
state = getNewContentListState(state, newState, value, id);
}

Related

Existing state editing in Riverpod / Flutter

How I can manipulate the existing state in Riverpod. 'm a beginner about Flutter and Riverpod. When I try add one to Order error pops up and says:
Error: A value of type 'int' can't be assigned to a variable of type
'List'.
final OrderPaperProvider = StateNotifierProvider<OrderPaper, List<Order>>((ref) {
return OrderPaper();
});
#immutable
class Order {
final String product_id;
final String product_name;
final int product_price;
final int product_count;
Order({required this.product_id, required this.product_name, required this.product_price, required this.product_count});
Order copyWith({product_id, product_name, product_price, product_count}) {
return Order(
product_id: product_id,
product_name: product_name,
product_price: product_price,
product_count: product_count,
);
}
}
class OrderPaper extends StateNotifier<List<Order>> {
OrderPaper() : super([]);
void addOrder(Order order) {
for (var x = 0; x < state.length; x++) {
if (state[x].product_id == order.product_id) {
addOneToExistingOrder(x, order);
return;
}
}
state = [...state, order];
}
void removeOrder(String product_id) {
state = [
for (final order in state)
if (order.product_id != order) order,
];
}
void addOneToExistingOrder(index, Order order) {
state = state[index].product_count + 1; // <--------- Error in this line
}
void clearOrderPaper() {
state = [];
}
}
What is happening in the code you posted is basically this:
You are telling it to update the state which is a List<Order> with an integer.
This is because state[index].product_count + 1 actually equals a number, for example 1+2 = 3.
So you are telling it, state = 3, and this causes your error.
What you need to do, is create a new state with the list of items and the edited item, like this (you don't need to pass the index, you can get it in the function):
void addOrder(Order order) {
//find if the product is in the list. The index will not be -1.
final index = state.indexWhere((entry) => entry.product_count == order. product_count);
if (index != -1) {
//if the item is in the list, we just edit the count
state = [
...state.sublist(0, index),
order.copyWith(product_count: state[index].product_count + 1),
...state.sublist(index + 1),
];
}else {
//otherwise, just add it as a new entry.
state = [...state, order],
}
}

how to check if a typing value contains a list of map

I have a list of map, so I want to check If the value I type contains any of the key value before adding.
here is my code:
for (var check in disciplineList) {
if (check.containsKey('degree') ||
!check.containsKey('degree')) {
if (check['degree'] != discipline.text) {
disciplineList.add({
'degree': discipline.text,
'date': currentDate
});
setState1(() {});
setState(() {});
discipline.clear();
currentDate = DateTime.now();
print(disciplineList);
} else {
openCustomDialog(
context: context,
body: '',
heading: 'Item Already Exists!');
print("Item Already Exists!");
}
}
}
In case you have some List of Maps listOfMaps and you want to check if it contains
1- a specific key
you can do so like this:
bool doesItContainKey(var key)
{
return listOfMaps.any((element) => element.keys.contains(key));
}
2- a specific value
you can do so like this:
bool doesItContainValue(var value)
{
return listOfMaps.any((element) => element.values.contains(value));
}
3- a specific map:
you can do so like this:
bool doesItContainMap(var map)
{
return listOfMaps.any((element) => element==map);
}

Fixed List is not updating with for loop - Flutter

I've a fixed list reservedGuest. After checking the condition in for loop I want to update the seats if the membership date has expired. The list is not updating. The code is as follows. PS. The List is filled through API on init().
class MyClubController extends GetxController {
List goldLane = List.filled(3, null, growable: false);
void _alterLanesOnContractEnds() {
for (var i in goldLane) {
print("\n\n I: $i");
if (i == null ||
DateTime.parse(i['contractEnds']).isBefore(
DateTime.now(),
)) {
i = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
}
A for-in loop will not allow you to reassign elements of the List. When you do:
for (var i in goldLane) {
// ...
i = null;
}
you are reassigning what the local i variable refers to, not mutating the goldLane List.
You instead can iterate with an index:
void _alterLanesOnContractEnds() {
for (var i = 0; i < goldLane.length; i += 1) {
var element = goldLane[i];
print("\n\n I: $element");
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
goldLane[i] = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
You can just create a new List where unqualified guests are nullified. For example,
void _alterLanesOnContractEnds() {
goldLane = goldLane.map(
(guest) => guest == null || DateTime.parse(guest['contractEnds']).isBefore(DateTime.now()) ? null: guest
).toList(growable: false);
update();
}
You should not and cannot modify a list while iterating with its iterator.
Elaborated by Jamesdlin,
Modifying the elements of a List while iterating is fine. Modifying
the length of the List while iterating is not, but that won't be a
problem for a non-growable List.
The bottom line is you should not mutate the size of the list while iterating.
I solved it by using
goldLane.forEach(
(element) {
print('\n\n ELEMENT: $element');
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
int ix = goldLane.indexWhere(
(element) => element != null
? DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)
: true,
);
goldLane[ix] = null;
} else {
print('Cannot be removed');
}
},
);
Yet I'll test the other answers. Thank You.

Can object properties be used as function parameters?

I have a class with several Boolean properties:
class aTest {
String name;
bool twoGroups;
bool continuous;
bool parametric;
bool covariates;
bool paired;
aTest(
{this.name,
this.twoGroups,
this.continuous,
this.parametric,
this.covariates,
this.paired});
} //end aTest
I also have a list with instances of aTest:
List<aTest> testList = [
aTest(
name: "independent samples t-test",
twoGroups: true,
continuous: true,
parametric: true,
covariates: false,
paired: false),
//followed by a bunch of similar objects
]
Elsewhere in my app I filter the List<aTest> with procedures like:
void isParametric(bool value) {
List<aTest> newList = [];
for (aTest test in testList) {
if (test.parametric == value || test.parametric == null) {
newList.add(test);
}
}
testList = newList;
}
void isTwoGroups(bool value) {
List<aTest> newList = [];
for (aTest test in testList) {
if (test.twoGroups == value || test.twoGroups == null) {
newList.add(test);
}
}
testList = newList;
}
(I don't know whether this is the best way to filter and remove objects from the List.) All that differs among these procedures is an object property, e.g., test.parametric and test.twoGroups in the code above.
Is there a way to refactor the code? Something like
void filter (aBooleanPropertyGoesHere, bool value)
You can simply filter with the lists with one liner by where method.
var parametricList = testList.where((i) => (i.continuous && i.parametric == null)).toList()
var twoGroupsList = testList.where((i) => (test.twoGroups == value || test.twoGroups == null)).toList()
Something like this https://dartpad.dev/79a7e9aa5882af745b6ff2cb55815921
For detailed explanation check out the documentation

How to map each item from observable to another one that comes from async function?

I want to
1.map item from observable to another one if it has already saved in database.
2.otherwise, use it as it is.
and keep their order in result.
Saved item has some property like tag, and item from observable is 'raw', it doesn't have any property.
I wrote code like this and run testMethod.
class Item {
final String key;
String tag;
Item(this.key);
#override
String toString() {
return ('key:$key,tag:$tag');
}
}
class Sample {
///this will generate observable with 'raw' items.
static Observable<Item> getItems() {
return Observable.range(1, 5).map((index) => Item(index.toString()));
}
///this will find saved item from repository if it exists.
static Future<Item> findItemByKey(String key) async {
//simulate database search
await Future.delayed(Duration(seconds: 1));
if (key == '1' || key == '4') {
final item = Item(key)..tag = 'saved';
return item;
} else
return null;
}
static void testMethod() {
getItems().map((item) async {
final savedItem = await findItemByKey(item.key);
if (savedItem == null) {
print('not saved:$item');
return item;
} else {
print('saved:$savedItem');
return savedItem;
}
}).listen((item) {});
}
The result is not expected one.
expected:
saved:key:1,tag:saved
not saved:key:2,tag:null
not saved:key:3,tag:null
saved:key:4,tag:saved
not saved:key:5,tag:null
actual:
not saved:key:2,tag:null
not saved:key:3,tag:null
not saved:key:5,tag:null
saved:key:1,tag:saved
saved:key:4,tag:saved
How to keep their order in result?
I answer myself to close this question.
According to pskink's comment, use asyncMap or concatMap solve my problem. Thanks!!
below is new implementation of testMethod.
asyncMap version:
getItems().asyncMap((item) {
final savedItem = findItemByKey(item.key);
if (savedItem != null)
return savedItem;
else
return Future.value(item);
}).listen(print);
concatMap version:
getItems().concatMap((item) {
final savedItem = findItemByKey(item.key);
if (savedItem != null)
return Observable.fromFuture(savedItem);
else
return Observable.just(item);
}).listen(print);