I think the second example in your twiddle is doing what you want it to, by explicitly opting in to two-way binding. That’s a totally fine way to do it.
The alternative is to pass the value and an action for changing the value separately into each component.
Ah, I see. Your issue is that you’re trying to directly update members of a list. There is a general issue here that isn’t Ember-specific, it’s about Javascript value-vs-reference.
Consider an example snippet like:
let list = ['a', 'b', 'c'];
for (let item of list) {
changeItemToD(item);
}
console.log(list);
Imagine how you could write the function changeItemToD such that the console.log prints ['d', 'd', 'd']. If you think about it for a bit, you’ll realize it’s impossible. No matter what the changeItemToD function does, it can’t alter the list because it doesn’t even have a reference to the list.
This is analogous to what’s happening in your example. Each component is only receiving one of the items from the list, so it can’t actually change the list itself.
Here’s a forked version of the gist that works. I’m passing actions down to the components that they can use to actually modify the list. In this case, I kept a native Array like you were using, so in order to tell Ember that it changes I’m recomputing a new array via map and replacing the original value with this.set.
Both these implementations are equally good ways to do it. I tend to favor the native Array when the cost of recomputing a whole array is low (which it often is), because there’s less ember-specific API to learn (all you need to know about is set).
I simplified my twiddle to get it working but removed the object which passed object references which skips the whole problem.
Here is an updated twiddle with a more real-life example of a dynamic form that doesn’t get affected by the direct value binding and uses an object value instead.