Flutter - different between the real value and the displayed value - flutter

I am facing very strange problem.
I want to implement the option to remove rows from DataTable, and therefore I implemented the following method:
onRemoveRow() {
setState(
() {
lastRowIndex -= selectedGeneLists.length;
geneLists.removeWhere((element) => selectedGeneLists.contains(element));
for (int i = 0; i < geneLists.length; i++) {
GenesListObjIndexed genesListObjIndexed = geneLists[i];
genesListObjIndexed.index = i;
}
selectedGeneLists = [];
},
);
}
This function should modify the list that store the table's data, and the expectation is that when I delete the items from the list the items will be deleted from the table.
But you can see here the following problem (the selected line isn't been removed):
The strange this is when I debug and check the value of the list it's look great and as expected, so what can be the problem?

Use the key property to uniquely identify each row and delete the row with the key value.

Related

SAPUI5 - Clearing valueState of input fields in ui.table

I'm having troubles resetting the valueState of input fields contained in a table cell. I'm clearing the model so the data is reset but the valueState is set on the view so it persists.
I've tried getting the input field byId and setting the value state as "None" but that doesn't affect the cells of the table.
Does anyone have an idea of how this can be achieved?
Image of cell with value state "Error"
If you really don't want to work with data model, you can just loop over the table and set the ValueState to None.
Code Example:
var aRows, aCells;
aRows = this.byId("table.id").getRows();
for ( var i = 0; aRows.length; i++) {
aCells = aRows[i].getCells();
for ( var j = 0; aCells.length; j++) {
if ( aCells[j] is an input element ) {
aCells[j].setValueState(sap.ui.core.ValueState.None);
}
}
}

Flutter Remove Multiple List Items In For Loop (Multiple Returns In A For Loop)

I have a list of food items. That has a category, subCategory1, subCategory2 ect.
When the user unselects an category item. They are also unselecting the subCategory1, subCatategory2 items etc as they are children of the original categogory item like this:
So I have a for loop that is running through looking for children category list elements and removing them like this:
// Remove a category item and all of its children
if (categoryType == "category") {
List<String> subCategory1Children = List<String>.from(
snapshot.data.documents[gridIndex]['subCategory1Children']);
// Remove the subcategory items
for (int i = 0; i < foodDrinkMenuElements['subCategory1'].length; i++) {
String subID = foodDrinkMenuElements['subCategory1'][i];
int removalIndex = _indexOfListGridElement('subCategory1', subID);
if (subCategory1Children.contains(subID)) {
_removeCategoryGridItem(removalIndex, subID, 'subCategory1');
}
}
//Remove the actual item being pressed
_removeCategoryGridItem(listIndex + 1, id, categoryType);
}
Which calls _removeCategoryGridItem() like this:
void _removeCategoryGridItem(int removalIndex, String id, String categoryType) {
_FoodandDrinkKey.currentState.removeItem(removalIndex,
(BuildContext context, Animation<double> animation) {
return _buildListItem(removalIndex, animation);
});
foodDrinkMenuElements[categoryType].remove(id);
}
The For loop is always finishing after 1 list item is removed. I assume this is because of the return statement in the function _removeCategoryGridItem.
I have seen other answers that say to put it in an list and run through the list but I don't see how that applies here.
Thanks for your help
The For loop is always finishing after 1 list item is removed. I assume this is because of the return statement in the function _removeCategoryGridItem.
No, generally the only way that a function could break out of a loop in a calling function is by throwing an exception.
I don't know what type foodDrinkMenuElements[categoryType] returns, but presuming that it's a List, Map, or Set, you cannot remove items from the collection while you iterating over the collection.
From the List documentation:
It is generally not allowed to modify the list's length (adding or removing elements) while an operation on the list is being performed.... Changing the list's length while it is being iterated ... will break the iteration.
There is similar language for Map and Set.
I have seen other answers that say to put it in an list and run through the list but I don't see how that applies here.
That is exactly what you should do: you should queue which items to remove and then process the queue to avoid mutating the same collection you're iterating over:
final pendingRemoves = List<void Function()>[];
// Remove the subcategory items
for (int i = 0; i < foodDrinkMenuElements['subCategory1'].length; i++) {
String subID = foodDrinkMenuElements['subCategory1'][i];
int removalIndex = _indexOfListGridElement('subCategory1', subID);
if (subCategory1Children.contains(subID)) {
pendingRemoves.add(() =>
_removeCategoryGridItem(removalIndex, subID, 'subCategory1'));
}
}
// Since an index is involved, you also need to remove in reverse order so that
// the queued indices still refer to the same elements.
for (pendingRemove in pendingRemoves.reversed) {
pendingRemove();
}
//Remove the actual item being pressed
_removeCategoryGridItem(listIndex + 1, id, categoryType);

Cannot remove value storage ionic 3

I would like to remove value in Ionic3 storage but i can't:
item is the id of the station
removeItem(item){
this.storage.get('thestations').then((val) => {
for(var i = 0; i < val.length; i++)
{
if(val[i].id == item) {
this.storage.remove(i);
}
}
});
}
I also tried that to delete the row with the key number 5 but still the same problem:
this.storage.remove('5');
first of all, the storage is a key value store. so when you want to delete an entire item you need to call storage.remove(key)
however when you have an array stored and want to remove an item you need to get the array first, modify it and then save it again.
you cannot work/delete on the storage reference

Sort/Order an Undetermined Number of Columns (LINQ\Entity Framework)

Need to sort/order a list of data based on an undetermined number of columns (1 or more).
What i'm trying to do is loop through the desired columns and add an OrderBy or ThenBy based on their number to the query'd list, but i'm unsuccessful...
Done this, but it doesn't compile:
var query = GetAllItems(); //returns a IQueriable list of items
//for each selected column
for (int i = 0; i < param.Columns.Length; i++)
{
if (i == 0)
{
query = query.OrderBy(x => x.GetType().GetProperty(param.Columns[i].Name));
}
else
{
//ERROR: IQueriable does not contain a definition for "ThenBy" and no extension method "ThenBy"...
query = query.ThenBy(x => x.GetType().GetProperty(param.Columns[i].Data));
}
}
How can i resolve this issue? Or any alternative to accomplish this requirement?
SOLUTION: #Dave-Kidder's solution is well thought and resolves the compile errors i had. Just one problem, OrderBy only executes (actually sorts the results) after a ToList() cast. This is an issue because i can't convert a ToList back to an IOrderedQueryable.
So, after some research i came across a solution that resolve all my issues.
Microsoft assembly for the .Net 4.0 Dynamic language functionality: https://github.com/kahanu/System.Linq.Dynamic
using System.Linq.Dynamic; //need to install this package
Updated Code:
var query = GetAllItems(); //returns a IQueriable list of items
List<string> orderByColumnList = new List<string>(); //list of columns to sort
for (int i = 0; i < param.Columns.Length; i++)
{
string column = param.Columns[i].Name;
string direction = param.Columns[i].Dir;
//ex.: "columnA ASC"
string orderByColumn = column + " " + direction;
//add column to list
orderByColumnList.Add(orderBy);
}
//convert list to comma delimited string
string orderBy = String.Join(",", orderByColumnList.ToArray());
//sort by all columns, yay! :-D
query.OrderBy(orderBy).ToList();
The problem is that ThenBy is not defined on IQueryable, but on the IOrderedQueryable interface (which is what IQueryable.OrderBy returns). So you need to define a new variable for the IOrderedQueryable in order to do subsequent ThenBy calls. I changed the original code a bit to use System.Data.DataTable (to get a similar structure to your "param" object). The code also assumes that there is at least one column in the DataTable.
// using System.Data.DataTable to provide similar object structure as OP
DataTable param = new DataTable();
IQueryable<DataTable> query = new List<DataTable>().AsQueryable();
// OrderBy returns IOrderedQueryable<TSource>, which is the interface that defines
// "ThenBy" so we need to assign it to a different variable if we wish to make subsequent
// calls to ThenBy
var orderedQuery = query.OrderBy(x => x.GetType().GetProperty(param.Columns[0].ColumnName));
//for each other selected column
for (int i = 1; i < param.Columns.Count; i++)
{
orderedQuery = orderedQuery.ThenBy(x => x.GetType().GetProperty(param.Columns[i].ColumnName));
}
you should write ThenBy after OrderBy like this:
query = query
.OrderBy(t=> // your condition)
.ThenBy(t=> // next condition);

Filter getElementsByTagName list by option values

I'm using getElementsByTagName to return all the select lists on a page - is it possible to then filter these based upon an option value, ie of the first or second item in the list?
The reason is that for reasons I won't go into here there are a block of select lists with number values (1,2,3,4,5 etc) and others which have text values (Blue and Black, Red and Black etc) and I only want the scripting I have to run on the ones with numerical values. I can't add a class to them which would more easily let me do this however I can be certain that the first option value in the list will be "1".
Therefore is there a way to filter the returned list of selects on the page by only those whose first option value is "1"?
I am pretty sure that there is a better solution, but for the moment you can try something like:
var allSelect = document.getElementsByTagName("select");
var result = filterBy(allSelect, 0/*0 == The first option*/, "1"/* 1 == the value of the first option*/);
function filterBy(allSelect, index, theValue) {
var result = [];
for (var i = 0; i < allSelect.length; i++) {
if(allSelect[i].options[index].value == theValue ) {
result.push(allSelect[i]);
}
}
return result;
}
I managed to get this working by wrapping a simple IF statement around the action to be performed (in this case, disabling options) as follows:
inputs = document.getElementsByTagName('select');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].options[1].text == 1) {
// perform action required
}
}
No doubt there is a slicker or more economic way to do this but the main thing is it works for me.