I'm using two variables with the same value. Variable A is an initial variable and variable B is the one that I use to apply changes, so when I want to reset variable B I just assign A to it, the problem is each time I do it, the changes of B then applied to both. I have look in many places and these are the solutions I tried:
List.toList()
_fields!.clear(); _fields = _initFields!.toList();
Spread operator (...)
_fields!.clear(); _fields = [...?_initFields];
Also tried the ones below from this post: Dart/Flutter – How to clone/copy a list
var newNumbers = List.from(numbers);
var newNumbers = List.generate(numbers.length, (index) => numbers[index]);
var newNumbers = List.of(numbers);
var newNumbers = List.unmodifiable(numbers);
Here the complete code:
import 'package:project/utilities/classes/filter_field.dart';
class FilterLogic {
List<FilterField>? _initFields = [];
List<FilterField>? _fields = [];
bool? listComplete = false;
void addField(FilterField? field) {
_fields!.add(field!);
}
void addInitField(FilterField? field) {
_initFields!.add(field!);
}
List<FilterField>? getFields() {
return _fields;
}
void resetFieldsToOriginal() {
_fields!.clear();
_fields = [...?_initFields!];
}
void showFields() {
print('_fields --------------------------------------------------------------------------------------');
_fields!.forEach((element) {
if(element.checked == true) {
print({ element.checked, element.field, element.filteredApplied, element.criteria, element.filteringOperators});
}
});
print('_initFields --------------------------------------------------------------------------------------');
_initFields!.forEach((element) {
if(element.checked == true) {
print({ element.checked, element.field, element.filteredApplied, element.criteria, element.filteringOperators});
}
});
}
}
Here is how I fill both variables:
filterCol.forEach((column) {
String? filteredApplied;
String? filteredCriteria = 'None';
bool checked = false;
filtersList.forEach((element) {
if (column.field == element.field) {
filteredApplied = element.operator;
filteredCriteria = element.criteria;
checked = true;
}
});
FilterField field = FilterField(
filteredApplied: filteredApplied,
field: column.field,
label: column.label,
filteringOperators: column.filteringOperators,
criteria: filteredCriteria,
checked: checked == true ? true : false,
);
FilterField initField = FilterField(
filteredApplied: filteredApplied,
field: column.field,
label: column.label,
filteringOperators: column.filteringOperators,
criteria: filteredCriteria,
checked: checked == true ? true : false,
);
setState(() {
filterLogic.addField(field);
filterLogic.addInitField(initField);
});
});
Here where I call the reset method:
DialogButton(
width: 106.25,
child: Text(
"CANCEL",
style: TextStyle(
color: Colors.white, fontSize: 14, fontFamily: 'Chivo'),
),
onPressed: () => {
Navigator.of(context).pop(),
setState(() {
filterLogic.resetFieldsToOriginal(); // <-------------
})
},
color: Color.fromRGBO(84, 84, 84, 1),
radius: BorderRadius.circular(0.0),
),
CodePudding user response:
It's not enough just to copy the list cause your new list has references to the same FilterField
instances. That means if you change any FilterField
in the new list the same changes would be in the old one. So in your case, you need to make a so-called deep
clone. You can create a method for that:
class FilterField {
// ... other code
FilterField CopyWith() {
return new FilterField(...);
}
}
and then you could something like that:
var newList = oldList.toList().map((item) => item.CopyWith()).toList();
and now you could change the lists separately.
But be aware that if FilterField
has any other instances of classes that need to be changed you need to create new instances of those instances either. That's why it's called a deep clone.
Hope that's what you were looking for.