Reputation: 687
I need to iterate through a collection of child views (Which are UI Widgets) and tell them to remove themselves from the app. I have ensured that all the childViews are present in the collection, however this code will only call removeIfSelected() on a few of the childViews/widgets at a time:
widgets = container.get('childViews')
widget.removeIfSelected() for widget in widgets
For example, if there are 3 widgets, the first time this is run (via delete button) 2 widgets are removed. I have to click the button again to remove the last widget.
If there are 2 it will remove one widget. If there are 4 or more, all but 2 widgets are removed, and I have to click delete 2 more times to remove the last two.
My initial solution was to run the loop 3 times which guarantees all widgets are removed, however this did not pass code review and I have to find a real solution. I am not sure if this is a coffeescript problem or an Ember.js problem. How can I ensure that the loop executes completely?
Upvotes: 0
Views: 168
Reputation: 434615
Sounds like widget.removeIfSelected()
is altering the widgets
array behind your back so as soon as remove something, the lengths and indexes in your for
loop get all screwed up. Consider this loop:
a = [ 0, 1, 2, 3, 4, 5 ]
for e, i in a
console.log(i) if(i % 2 == 0)
That will obviously produce 0, 2, 4
in the console. However, this:
a = [ 0, 1, 2, 3, 4, 5 ]
for e, i in a
a.splice(i, 1) if(i % 2 == 0)
console.log(a)
leaves you with [1, 2, 4, 5]
in a
because a
is being modified while it is being looped over.
There are two common solutions to this:
The first would look like this:
for i in [widgets.length - 1 .. 0] by -1
widget.removeIfSelected()
The second would look like this:
widgets = clone(container.get('childViews'))
widget.removeIfSelected() for widget in widgets
Where clone
is whatever you have available to make (shallow) copies of an array. If you have Underscore kicking around then you could use _.clone
:
widgets = _(container.get('childViews')).clone()
You could also do it by hand:
clone = (a) -> e for e in a
Upvotes: 2