Issue With Adding and Deleting Function in Flutter - flutter

I have these two functions that should add and remove the item on the list. The adding one should also calculate the total sum of all items, but it doesn't work quite exactly as it should. Here is the adding function:
Future getTotal(item) async {
int counter = 0;
counter += int.parse(item);
totalPrice.add(counter);
_totalPrice.forEach((element) => counter += element);
print(totalPrice);
print(counter);
return totalPrice;
}
It first declares counter (which is sum basically), then it should onTap calculate the total sum of all items, but I get this problem, where it adds items properly, but the counter adds one extra item on the first tap, like the counter is added twice in the beginning, I suspect this code is the issue:
counter += int.parse(item);
totalPrice.add(counter);
Here is the issue in pictures:
Now for the delete function
I have this simple delete function, but it doesn't seem to remove any item onTap:
deleteSumItem(item) {
_totalPrice.remove(item);
notifyListeners();
print(totalPrice);
}
It should work together with the getTotal(item) function, removing the particular item from it, but as I mentioned, it doesn't seem to do anything, and returns full list each tap.
I hope I was clear, I never seem to figure out the simple issues. Thank you!

You are adding the element twice here: _totalPrice.forEach((element) => counter += element);
with regards to removing, you are using (mainly) totalPrice when adding but _totalPrice when removing. See the difference?

Related

Adding and Removing Items From Flutter Lists Dynamically

I have these two functions that should add the item onTap to the list, and then another one to delete the item. The first one (adding the item) works fine, but the delete one doesn't seem to delete anything. I suspect the issue is that the counter variable is not global, but for some reason it doesn't work fine when I add it globally (and I would need it to be). Here's the full code:
List<int> _totalPrice = [];
List<int> get totalPrice => _totalPrice;
here is the add item function
Future getTotal(item) async {
int counter = 0;
_totalPrice.add(int.parse(item));
_totalPrice.forEach((element) => counter += element);
print('LIST: $_totalPrice');
print('SUM: $counter');
return counter;
}
here is the delete function that doesn't remove anything
deleteSumItem(String item) {
_totalPrice.remove(item);
}
I think the issue is that the counter variable isn't global, I am not sure how to add it globally to change dynamically.
So, here your code shows that you are putting int in your _totalPrice list, but you are trying to remove the String from the list. It will not be found to be deleted.
So, you can change the data type of your list into String or you can write the below function to delete an item where the function only takes an int
deleteSumItem(int item) {
_totalPrice.remove(item);
}
Also you can remove an item by below line of code (If you have a custom type of data in your list):
_totalPrice.removeWhere((item) => item.price == '520')

Row selection using forEachNode very slow

I am using AG Grid React. I have a thousand row of data. I am trying to select a range of rows based upon their indices.
gridOptions.api.forEachNode(node => {
if (node.childIndex >= startIndex && node.childIndex < endIndex) {
node.setSelected(true)
}
});
This is turning out to be very sow and typically takes 30 seconds on the UI. Seems like setSelected triggers multiple render cycles. What is the correct way of doing it?
The problem is - setSelected(newValue) dispatches events. When we do it in a loop for a thousand items(say) - there are a thousand events, a thousand requests queued for asynchronous update in React which can be accounted for all the delay.
I fixed it using another version of setSelected - setSelected(newValue, clearSelection, suppressFinishActions). Unfortunately, this is not written in the official documentation.
The idea is to use this version for all but the last selection, so that all the event dispatches are supressed and use the normal selection we have been using forever to select the last element so that it also triggers necessary events for onRowSelected, onSelectionChanged, etc. to work normally.
this.api.forEachNodeAfterFilter(node => {
if (node.childIndex >= startIndex && node.childIndex < endIndex) {
selectedNodes.push(node);
}
});
if (selectedNodes.length > 0) {
// setSelected re-renders every time so use suppressFinishActions except last one
for (let i = 0; i < selectedNodes.length - 1; i++) {
selectedNodes[i].setSelected(true, false, true);
}
selectedNodes[selectedNodes.length - 1].setSelected(true);
}
You can try to use pagination to load the chunk of data thane the whole data.
Pagination Docs
Make sure that you don't have subscribed to any events that may cause your code to be slow, e.g. onRowSelected, onSelectionChanged. These get triggered for each
node.setSelected(true)
If you do have any of these subscribed events, one possible way to solve this, is to unsubscribe before the loop and then re-subscribe after the loop.
Also, depending on your use case you may want to use
forEachNodeAfterFilter(node)
in order to only loop through visible nodes instead of
forEachNode(node)

scala : double "selection changed" event raised for ListView component

here is the part of code:
val lsv_syns = new ListView[String]()
val scp_syns = new ScrollPane() {
listenTo(lsv_syns.mouse.moves,lsv_syns.selection)
reactions += {
case me: MouseExited => {
txf_mot.requestFocus()
}
case SelectionChanged(`lsv_syns`)=> {
println("sélection:"+lsv_syns.selection.items(0))
}
}
}
As you can see, the listView is in a scrollPane; don't pay attention to the mouseExited event, the interesting thing is the selectionChanged, which seems to be called twice when I only click on time on an other line, because the println is called two times.
thanks.
Well i also recently worked with a ListView and now that you mentioned it, it also does my calculation twice.
The answer seems to be related to mouse events. Following the stack trace SelectionChanged is called twice. One coming from the Java event MousePressed and one from MouseReleased.
When you change the selection with KeyEvents it is only called once.
My first (and I guess not nice) idea to avoid the problem would be to ignore one of the events:
reactions += {
case SelectionChanged(`lsv_syns`) if !lsv_syns.selection.adjusting => {
println("sélection:"+lsv_syns.selection.items(0))
}
}
Both ListSelection events share the same data except getValueIsAdjusting. So if you check for it you can avoid doing your stuff twice.
Warning: !lsv_syns.selection.adjusting will result in printing on key release and not on press!
If you put lsv_syns.selection.adjusting it will correspond to key press but it will also filter key events. As I said. Not nice at all...

Knockoutjs nested view model updates

I'm trying to understand how I can have nested knockoutjs view models with a little fiddle that lists some items and on click of a button, it shows the details of that item. Then, I have a button that updates the Id property of each item by adding 15 to each ones but for a reason, they end up having all the same value at the end.
Can someone enlighten me?
Thanks!
The fiddle in question
It's your .Name computed property. The Id change works correctly.
http://fiddle.jshell.net/Y3JXD/1/
The item in the closure was always the last item in the list after the first execution. Remember that the computed is updated any time the observable changes. So, the first time during setup, it worked fine as item was the item from the loop. But, what was captured in the closure was just item (the 15th item), not the one that was for that specific loop instance.
Update: forgot about the second parameter to computed as suggested in a comment.
http://fiddle.jshell.net/Y3JXD/1/
item.Name = ko.computed(function () { return 'Item_' + item.Id(); }, item);
Here's another technique for wrapping the reference in a closure, and capturing the right item instance (just as a demonstration for what needs to happen to capture the proper scope).
self.loadItems = function () {
for (var i = 0; i < 15; i++) {
var item = ko.mapping.fromJS({
Id: i
});
self.items.push(item);
(function (item) {
item.Name = ko.computed(function () {
return 'Item_' + item.Id();
});
})(item);
}
};
Could you move the Name property to the itemModel?
self.Name = ko.computed(function() {
return 'Item_' + self.Id();
});
It seems odd to set it when you create the object, rather than when you consume it.

Meteor: Elements from CollectionA re-rendering when I insert to CollectionB

I'm attempting to fade-in new elements in a reactive {{#each}} of the comments posted by users.
I have a code sample at https://gist.github.com/3119147 of a very simple comments section (textarea and new comment insert code not included, but it's very boilerplate.). Included is a snippet of CSS where I give .comment.fresh { opacity: 0; }, and then in my script, I have:
Template.individual_comment.postedago_str = function() {
var id = this._id;
Meteor.defer(function() {
$('#commentid_'+id+'.fresh').animate({'opacity':'1'}, function() {
$(this).removeClass('fresh');
});
});
return new Date(this.time).toString();
};
Which seems like a terrible place to execute an animation. My thinking is that each time a new comment is rendered, it will need to call all my Template.individual_comment.* functions, so that's why my animation defers from one of those. However, Meteor is calling Template.individual_comment.postedago_str() each time a different collection (Likes) is inserted to. This means I click the Like button, and my whole list of comments flashes white and fades back in (very annoying!).
I read the Meteor documentation and tried to figure out how to better slice up my templates so only chunks will update, and I added id="" attributes everywhere that seemed reasonable.. still this bug. Anyone know what's going on?
TIA!
As a workaround, you could wrap an {{if}} block around the fresh class on individual comments, that would check the comment's creation time and only add the fresh class in the first place if the comment is actually recent. Something like:
<div class="comment{{#if isActuallyFresh}} fresh{{/if}}" id="commentid_{{_id}}">
And then define the isActuallyFresh function:
Template.individual_comment.isActuallyFresh = function() {
if ((new Date().getTime() - this.time) < 300000) // less than 5 minutes old
return true;
else
return false;