What is a good way to do this in Ember 2.0? (No itemController, no ArrayController)

Also of note, if you are an intermediary component and are just passing along the action to your parent you do not have to use {{action "someName}} at all, you would just bind to the action you were provided from your parent. This makes it SUPER clear where this thing is coming from in the template (and removes silly boilerplate from your components just to “bubble” an action).

<!-- some top level template -->
<some-middleman on-selected={{action "onSelectChange"}}>
<!-- some-middlemans template -->
<some-enduser on-selected={{attrs.on-selected}}>
1 Like

Ah, great point. Wow I can’t wait for this.

This is just a little example, and not knowing anything about ReactJS, it doesn’t seem that this example is totally “data down”. If you make a change to the isSelected property of the model it doesn’t reflect itself in the checkbox in the selectable-item.

Using this approach, how would you make changing the model check or uncheck the checkbox?

Ah you’re right, it should be checked=item.isSelected, but then every time you click a checkbox, both the {{input}} helper and the action handler in the parent component toggle the property.

What you’d need is for {{input}} to be one-way, so it’d be something like

<input {{bind-attr checked=isSelected}} {{action 'change'}} type="checkbox">

so that when the user clicks, the action essentially goes straight to the handler (from the parent), which then updates the isSelected property, which then propagates the change back down to the checkbox.

I know this is a silly little example, but I’m learning about Ember, and I am trying to understand how things work.

I updated the original jsbin to use bind-attr like you mentioned, and added a one-way binding from the model’s isSelected to the selectable-item’s isSelected, to link those together:

The checkbox doesn’t toggle at all now, even though the selectable-item’s isSelected property is being toggled via the one-way binding.

@caleb Sorry for causing any confusion. This is more of a discussion about what things will look like in 2.0 land.

Because the current {{input]} helper was developed for a two-way-bindings world, it makes this example tricky.

Let’s just use a simple click event on a <p> tag. Hopefully this is a clearer example of data down, actions up:

Thanks for the help.

I like seeing a working example of this concept. Like you said in a post above, it seems that two-way bindings are useful in these types of nitty-gritty cases (binding for form elements), but using data bindings from top to bottom in your application might be a bad idea.

I’m looking forward to Ember 2.0!

I’d love to hear what the recommended pattern for this is. In our app, we have a few itemControllers that are really “helpers” for things like action handling and CP data transformation. They end up with a lot of reuse through out the app, but have different markup. Something like this:

{{#each user in loggedInUsers itemController="user"}}
  <label>Name:</label>  {{user.displayName}}
  <label>Last Login:</label> {{user.lastLogin}}
{{/each}}

In the above example, the user item controller has some actions and computed properties that are very frequently reused.

At first, I thought a replacement might look something like this:

{{#each user in loggedInUsers}}
  {{#user-widget user=user}}
    <label>Name:</label>{{controller.displayName}}
    <label>Last Login:</label> {{user.lastLogin}}
  {{/user-widget}}
{{/each}}

But that leaves me with a conundrum, how do I access the component scope within the template? {{controller}} doesn’t work, neither does {{view}}. Is there a way to do this? The same goes for action targets as well. Adding an {{action}} to the the user’s displayName will always target the controller for the template’s primary scope, not for the parent component.

So to boil it all down, if each and every user-widget looked the same, I’d just use that. But surely the recommendation isn’t to make 14 different user-widgets, right?

@workmanw My understanding is that block parameters will will solve this shortcoming of components.

{{#each user in loggedInUsers}}
  {{#user-widget user=user as |yieldedThing|}}
    <label>Name:</label>{{yieldedThing.displayName}}
    <label>Last Login:</label> {{user.lastLogin}}
  {{/user-widget}}
{{/each}}

I don’t know what that syntax looks like inside of the component. Anyone have more insight?

In the RFC the example with the {{#form-for}} component alludes to this.

Regarding actions, I know you can specify a target now, so I’m thinking you could still specify a target in Ember 2.0, so you could specify your yielded object as the target. All speculation here.

@mitchlloyd AH. That makes sense! Thanks Mitch!

If that is the recommended pattern, I’ll have to wait for block parameters to land before migrating away from itemController. Regardless, I’m happy to see the functionality will be preserved.

FYI - Block Params have landed in the Canary channel, and barring unforeseen issues will be enabled in 1.10 in a few weeks.

1 Like

Just come across this old issue and I find it interesting: https://github.com/emberjs/ember.js/pull/3424. When you get to nested ArrayControllers this is even hard to do in Components. Wonder what happened to the follow up on the issue?

@workmanw @rwjblue Just a guess. Does block params support delegating action handler like this:

{{#each user in loggedInUsers}}
  {{#user-widget user=user pendingUser="pendingUser" as |widget|}}
    <label>Name:</label> {{widget.displayName}}
    <button {{action "pendingUser" target=widget}}>Pending<button>
  {{/user-widget}}
{{/each}}

Or even this:

{{#each user in loggedInUsers}}
  <user-widget user=user pendingUser={{action "pendingUser"}} as |widget|>
    <label>Name:</label> {{widget.displayName}}
    <button on-click={{widget.pendingUser}}>Pending<button>
  </user-widget>
{{/each}}

How might you animate-in a component?

{{#each task in tasks}}
  {{task-item task=task}}    <--- only subsequently added tasks should animate
{{/each}}

Related jsbin

Array controllers would have been perfect for this (i.e. acknowledging the item has animated once)

@amk I’m not sure Embers traditional array controllers should be dealing with view/animation concerns.

Animation makes more sense with components. React has a model for animating components and it took inspiration from Angular. It is certainly something that needs to be considered.

Another thing React provides is access to an opaque children collection of all child components. Something like that may appear in Ember components as well, including the ‘ref’ property for being able to reference children by name.

The obvious pattern to me wrt collections of things and selection state is that the child component should send an action to the parent on select change and let it decide what to do. The parent may have single or multi select semantics and need to manage that. The selected state should be passed down to each child component from the parent.

Wrt to passing state down in the bigger picture immutable data types are built for this kind of thing and allow for very efficient subsetting of data without copying. I’m keen for Ember to give immutable data types some serious consideration as they have many payoffs including keeping the state unidirectional and undo/redo practically for free.

I was also thinking about this problem, my first shot at it is this: GitHub - piotrpalek/co-list: Ember-cli list addon (requires block params). I am curious about your opinion on going down this path, obviously what I’ve done with that list component is basically just an experiment.

1 Like

This ‘ref’ thing would be great, I’m in need for something like this to pass around references of components that are not in a parent-child relation. Polymer solves this through id=“xxx” and look-ups via normal getElementById() and as it’s DOM only you get the component instance which I think is quite nice.