I'm trying to handle some data for a flutter application, however I am getting the following error on my code:
The method 'add' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!').
Map<String, List<SourcefulListing>> sortedSkills = {};
QuerySnapshot listingSnapshot = await listingsRef.get();
List<SourcefulListing> listings = [];
for (int i = 0; i < listingSnapshot.docs.length; i++) {
listings.add(SourcefulListing.fromJson(
listingSnapshot.docs[i].data() as Map<String, dynamic>));
}
for (String skill in skills) {
for (SourcefulListing listing in listings) {
if (listing.selectedSkill == skill) {
if (sortedSkills[skill] == null || sortedSkills[skill] != []) {
sortedSkills[skill] = [listing];
} else {
sortedSkills[skill] = sortedSkills[skill].add(listing);
}
}
}
}
Basically I have a Map with Strings as key and List for the values. The for each loop should add the SourcefulListing object to the map, however there is an error on the .add method.
Any help would be much appreciated.
Try this,
Map<String, List<SourcefulListing>> sortedSkills = {};
QuerySnapshot listingSnapshot = await listingsRef.get();
List<SourcefulListing> listings = [];
for (int i = 0; i < listingSnapshot.docs.length; i++) {
listings.add(SourcefulListing.fromJson(
listingSnapshot.docs[i].data() as Map<String, dynamic>));
}
for (String skill in skills) {
for (SourcefulListing listing in listings) {
if (listing.selectedSkill == skill) {
if (sortedSkills[skill] == null || sortedSkills[skill] != []) {
sortedSkills[skill] = [listing];
} else {
sortedSkills[skill]?.add(listing); // changes made here
setState(() {}); // update ui
}
}
}
}
Null Safety : https://dart.dev/null-safety
The function below finds only one item in the list, even if there are multiple items, how do I fix this function to find all items?
List newList = [];
if (value.isNotEmpty) {
for (var element in pressures) {
if (element.pressure.contains(value) ||
element.date.toString().contains(value)) {
newList.clear();
newList.add(element);
}
}
items.value = newList;
} else {
items.value = pressures;
}
You are clearing the list on loop
if (value.isNotEmpty) {
newList.clear(); // you can clear it on top of the loop
for (var element in pressures) {
if (element.pressure.contains(value) ||
element.date.toString().contains(value)) {
// newList.clear(); //remove this
newList.add(element);
}
}
items.value = newList;
} else {
items.value = pressures;
}
How to search for 2 different parameters in a dart list?
Is there a simple method?
Can I solve the problem using contains?
void _runFilter(String searchKeyword) {
List<Product> results = [];
if (searchKeyword.isEmpty) {
results = allProducts;
} else {
results = allProducts.where(
(element) =>
element.name.toLowerCase().contains(searchKeyword.toLowerCase()) || element.image.toLowerCase().contains(searchKeyword.toLowerCase()),
),
)
.toList();
results = results +
allProducts
.where(
(element) => element.image.toLowerCase().contains(
searchKeyword.toLowerCase(),
),
)
.toList();
}
// refresh the UI
setState(() {
filteredProducts = results;
});
}
You can write all sorts of if-else-combinations in a closure. If you use the {} notation instead of => it will become clearer. Something like this will accomplish what you are looking for:
results = allProducts.where( (element) {
if ( element.name.toLowerCase().contains(searchKeyword.toLowerCase()) {
return true;
} else if ( element.image.toLowerCase().contains(searchKeyword.toLowerCase()) {
return true;
} else {
return false;
}
}).toList();
If this step is clear, you can then try to combine individual statements into a boolean combination via || or && if this looks more convenient in your code.
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);
}
I am using w2ui (1.5) and I would be interested in whether it is possible to use a filter that only delivers negative results
That means only records/keys which not fullfilling a certain criteria.
Like a condition "contains not" or "is not" in addition to
http://w2ui.com/web/docs/1.5/w2grid.textSearch.
Thanks!
Gordon
okay, a possible solution is
w2ui['grid'].search([{ field: var1, value: var2, operator: 'not in'}], 'OR');
I coded my own solution to this problem. This adds a way to use "not" for string and "!=" for number searches.
This function does the search and it is also used to store the grid advanced search popup in history state.
I'm sure this can be even more optimized, so please use this more like a guideline. Hope this helps somebody.
function searchExtend(event, grid) {
// if event is null, we do just the local search
var searchObj;
if (event == null) {
searchObj = grid;
} else {
searchObj = event;
}
// make a copy of old data
const oldSearchData = structuredClone(searchObj.searchData);
const oldSearchLogic = structuredClone(searchObj.searchLogic);
var searchData = searchObj.searchData;
var invertedSdata = [];
var toSplice = [];
// check operator if it's "not" or "!="
for (var i = 0; i < searchData.length; i++) {
var sdata = searchData[i];
// invert the condition
if (sdata.operator == "not") {
toSplice.push(i);
invertedSdata.push({
field: sdata.field,
type: sdata.type,
operator: "contains",
value: sdata.value
});
}
if (sdata.operator == "!=") {
toSplice.push(i);
invertedSdata.push({
field: sdata.field,
type: sdata.type,
operator: "=",
value: sdata.value
});
}
}
// remove all "not" and "!=" from searchData
for (var i in toSplice) {
searchData.splice(i, 1);
}
var foundIds = [];
// use inverted criteria to search
if (invertedSdata.length > 0) {
grid.searchData = invertedSdata;
grid.searchLogic = "OR";
grid.localSearch();
grid.searchLogic = oldSearchLogic;
// store found ids
foundIds = structuredClone(grid.last.searchIds);
}
if (foundIds.length > 0) {
// perform a search with original criteria - spliced "not" and "!="
grid.searchData = searchData;
grid.localSearch();
var allRecIds = structuredClone(grid.last.searchIds);
// if there's not any results, push push all recIds
if (grid.last.searchIds.length == 0) {
for (let i = 0; i < grid.records.length; i++) {
allRecIds.push(i);
}
}
// remove all ids found with inverted criteria from results. This way we do the "not" search
for (const id of foundIds) {
allRecIds.splice(allRecIds.indexOf(id), 1);
}
if (event != null) {
// let the search finish, then refresh grid
event.onComplete = function() {
refreshGrid(grid, allRecIds, oldSearchData);
setSearchState(grid);
}
} else {
// refresh the grid
refreshGrid(grid, allRecIds, oldSearchData);
setSearchState(grid);
}
return;
}
if (event != null) {
event.onComplete = function() {
setSearchState(grid); // store state
}
} else {
// refresh whole grid
refreshGrid(grid, allRecIds, oldSearchData);
setSearchState(grid);
}
}
function refreshGrid(grid, allRecIds, oldSearchData) {
grid.last.searchIds = allRecIds;
grid.total = grid.last.searchIds.length;
grid.searchData = oldSearchData;
grid.refresh();
}
function setSearchState(grid) {
history.replaceState(JSON.stringify(grid.searchData), "Search");
}
To use this, you have to call it from the grid's onSearch:
onSearch: function(event) {
searchExtend(event, w2ui["grid"]);
}
Also, if you want to use the history.state feature, it needs to be called from onLoad function:
onLoad: function(event) {
event.onComplete = function() {
console.log("History state: " + history.state);
if (history.state != null) {
w2ui["grid"].searchData = JSON.parse(history.state);
searchExtend(null, w2ui["grid"]);
}
}
To add operators, please use this reference.
This is my solution to the problem:
operators: {
'text': ['is', 'begins', 'contains', 'ends', 'not'], // could have "in" and "not in"
'number': ['=', 'between', '>', '<', '>=', '<=', '!='],
'date': ['is', 'between', {
oper: 'less',
text: 'before'
}, {
oper: 'more',
text: 'after'
}],
'list': ['is'],
'hex': ['is', 'between'],
'color': ['is', 'begins', 'contains', 'ends'],
'enum': ['in', 'not in']
}