List Component with nested "outlet" component for selected item


#1

Hi all, I spent a few days trying to solve this problem but I couldn’t find any good simple examples so I came up with a solution and wanted to share.

I had a non-component template version that looked like this (pseudo):

this.resource('items', function() {
  this.resource('item', { path: ':item_id' });
});

//items template
<ul>
  {{#each item in content}}
    <li>{{#link-to 'item' item}}{{item.name}}{{/link-to}}</li>
  {{/each}}
</ul>
{{outlet}}

//item details template
<ul>
    <li>{{item.desc}}</li>
    <li>{{item.price}}</li>
    <li>{{item.brand}}</li>
</ul>

When you click on the item, the details render into the outlet. But components have no outlet so you need to create a nested subcomponent. But how to render the selectedItem into the subcomponent?

my solution:

<script type="text/x-handlebars">
    <h2>list component with "outlet" for selected item</h2>
    {{list-box items=items}}
</script>
  
<script type="text/x-handlebars" data-template-name="components/list-box">
    <ul>
      {{#each item in items}}
        <li {{action 'select' item}}>{{item.name}}</li>
      {{/each}}
      </ul>
    {{item-details item=selectedItem}}
</script>

and add an action to track of the selected item:

App.ListBoxComponent = Ember.Component.extend({
selectedItem: Ember.computed.oneWay('items.firstObject'),
  actions: {
    select: function(item) {
      this.set('selectedItem',item);
    }
  }
})

Here’s the full example on jsbin

EDIT: anyone know the simplest way to autoselect the first item rather than selectedItem: “” ?
EDIT2: updated with @ninjatronic’s suggestion


Nested components and passing data
#2

You could do something like:

firstItem: Ember.computed.alias('items.firstObject')
selectedItem: Ember.computed.oneWay('firstItem')

#3

Thanks. @ninjatronic that worked perfectly. updated my example.