Looking for a pattern to help with cross-component communication

Imagine this component:

{{postal-address address=address format=format}}

<span {{action 'setAddressFormat' 'HTML'}}>View as HTML</span>

When setAddressFormat is clicked, the value ‘HTML’ is sent to the postal-address component (via the surrounding controller, which is managing the state).

This is fine so far.

However, now that Array (Item) Controllers have gone. How can this be achieved when there is more than one component?

I haven’t tested but I believe this should be the general idea.

    {{#each address in addresses}}
        {{postal-address address=address format=format}}
        <small {{action 'toggleAddressFormat'}}>
            Toggle format

Add a field format to your controller default to whatever your default is. Pass in the format to the component. When you change the format in the controller via the action the format should change because of the dat binding.

Edit fiddle - JSFiddle - Code Playground using block params should do it. In this case, I didn’t bother sending it up to the application controller since you can target the component itself to handle the action.

If you do send it up to the application controller… be careful since if you’re doing something async that component could be destroyed by the time the async operation completes.

{{#each address in addresses}}
  {{#postal-address address=address as |postal-component|}}
    <small {{action 'toggleFormat' target=postal-component}}>
      Toggle format

@jasonmit Ah haa, that’s it!

I’d read about block params, but wasn’t sure how they could help me. Thanks for the fiddle!

I ended up having to use targetObject= rather than target=

What’s the difference?

It’s used within the TargetActionSupport mixin:

Ember.Component overrides this targetObject to point the parentView.controller the default target, so the default implementation in the mixin above never gets hit, thus target is never looked at. So, you can’t use target on a component you need to override the targetObject.

The thing which handles the triggering the action, triggerAction (in the same mixin), is looking at targetObject not target.

I see.

I wonder if setting targetObject is considered an ‘ok’ thing to do?

I mean, if components really are meant to be these locked-down, self-contained things, overriding targetObject shouldn’t be allowed. But as in above example, there is a use case for setting target.