# How to use components for a table row

**URL:** <https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134>\
**Category:** Uncategorized\
**Created:** [May 4, 2014, 4:22pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134 "2014-05-04T16:22:02Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![joelataylor](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/joelataylor/32/15755_2.png) [@joelataylor](https://discuss.emberjs.com/u/joelataylor)\
**Post date:** [May 4, 2014, 4:22pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/1 "2014-05-04T16:22:02Z")

</div>

Hi! I’d like to get some feedback on how I should build a component for my table row.

I’d like the row to be plain text, and then when the user clicks the edit button, it turns the columns into input fields.

I have two questions:

1. When I call the component and pass in the appropriate variables, I’m getting an error: Uncaught TypeError: Cannot read property ‘firstChild’ of null
2. How do I tell a specific row that I’d like it to switch to the editing view?

Here’s my Template:

```
<table class="services table">
  <thead>
    <tr>
      <td>date</td>
      <td>type</td>
      <td>description</td>
      <td>price/per</td>
      <td>quantity</td>
      <td>total</td>
      <td>actions</td>
    </tr>
  </thead>
  <tbody class="table-striped">
  {{#each services}}
    {{service-table-row service=newService servicePer=servicePer serviceTypes=serviceTypes}}
  {{/each}}
    <tr>
      <td colspan="5" class="total-title">Total:</td>
      <td colspan="2" class="total-amount">${{controllers.project.total}}</td>
    </tr>
  </tbody>
  <tfoot class="add-service form-inline" role="form">
    {{service-table-row service=newService servicePer=servicePer serviceTypes=serviceTypes isEditing=true}}
  </tfoot>
</table>

```

My component template:

```
<tr>
  <td>
    {{#if isEditing}}
      <label for="date" class="sr-only">Date:</label>
      {{input type="date" value=date class="form-control input-sm"}}
    {{else}}
      {{date}}
    {{/if}}
  </td>
  <td>
    {{#if isEditing}}
      <label for="type" class="sr-only">Type:</label>
      {{view Ember.Select content=serviceTypes value=type class="form-control input-sm"}}
    {{else}}
      {{type}}
    {{/if}}
  </td>
  <td>
    {{#if isEditing}}
      <label for="description" class="sr-only">Description:</label>
      {{input type="text" value=description class="form-control input-sm input-description"}}
    {{else}}
      {{description}}
    {{/if}}
  </td>
  <td>
    {{#if isEditing}}
      <label for="price" class="sr-only">Price:</label>
      {{input type="number" value=price class="form-control input-sm"}}/
      {{view Ember.Select content=servicePer value=per class="form-control input-sm"}}
    {{else}}
      ${{price}}/{{per}}
    {{/if}}
  </td>
  <td>
    {{#if isEditing}}
      <label for="quantity" class="sr-only">Quantity:</label>
      {{input type="number" value=quantity class="form-control input-sm"}}
    {{else}}
      {{quantity}}
    {{/if}}
  </td>
  <td>
    ${{total}}
  </td>
  <td>
    {{#if isEditing}}
      <button {{action 'addService'}} class="btn btn-primary btn-xs">Add</button>
    {{else}}
      <a {{action 'editService' this}} class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-pencil"></span> Edit</a> <a {{action 'removeService' this}} class="btn btn-warning btn-xs"><span class="glyphicon glyphicon-remove-circle"></span> Delete</a>
    {{/if}}
  </td>
</tr>

```

This is my first post, so if I’m missing something, just let me know. 😄Thanks!

---

<div class="post-metadata">

**Author:** ![jonnii](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/jonnii/32/14279_2.png) [@jonnii](https://discuss.emberjs.com/u/jonnii)\
**Post date:** [May 4, 2014, 9:42pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/2 "2014-05-04T21:42:03Z")

</div>

Is there a reason why you went with the component route in this case and not an itemController?

Edit:

That said, the context of the current item in the `{{#each}}` will be `{{this}}`, so you should pass that into your component to represent the row. You could by setting `content=this` when using the component, which would then make it available within the component.

IIRC components don’t proxy calls to `content` like an `ObjectController` does, so if you want to use a value passed into the component you’ll need to do so explicitly. (note: i might be wrong about this…)

---

<div class="post-metadata">

**Author:** ![zackangelo](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/zackangelo/32/14491_2.png) [@zackangelo](https://discuss.emberjs.com/u/zackangelo)\
**Post date:** [May 6, 2014, 4:29pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/3 "2014-05-06T16:29:07Z")

</div>

I agree that this smells like the wrong job for a component. It may be more appropriate to use itemControllers like @jonnii suggested. But design considerations aside…

Have you looked at the DOM output from your component? It’s likely adding `<div>` tags for each instance of the component. Try creating an `Ember.Component` subclass for your component and setting it’s `tagName` property to `"tr"`:

```auto
var ServiceTableRowComponent = Ember.Component.extend({ 
    tagName: 'tr',
});

```

---

<div class="post-metadata">

**Author:** ![joelataylor](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/joelataylor/32/15755_2.png) [@joelataylor](https://discuss.emberjs.com/u/joelataylor)\
**Post date:** [May 9, 2014, 6:07pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/4 "2014-05-09T18:07:50Z")

</div>

Thanks guys - it’s been a bit of time since I’ve managed to get back to this - and I should’ve probably shared a lot more code.

However, I’d like to understand more about what you mean by itemControllers … I didn’t find anything with a quick google.

zackangelo - funny enough, it isn’t using 'div’s - it’s using 'tr’s - automatically. 😄

---

<div class="post-metadata">

**Author:** ![pc\_walid](https://avatars.discourse-cdn.com/v4/letter/p/71e660/32.png) [@pc\_walid](https://discuss.emberjs.com/u/pc_walid)\
**Post date:** [August 5, 2014, 3:18pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/5 "2014-08-05T15:18:34Z")

</div>

Very helpful !!! thank you for your answer 🙂

---

<div class="post-metadata">

**Author:** ![caranicas](https://avatars.discourse-cdn.com/v4/letter/c/41988e/32.png) [@caranicas](https://discuss.emberjs.com/u/caranicas)\
**Post date:** [September 5, 2014, 6:14pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/6 "2014-09-05T18:14:51Z")

</div>

New to Ember here, I am trying to so a similar thing. Can you explain why you would use an item controller over a component? I feel like a component would be the right tool for the job here, but maybe thats just because I have this new shiny hammer.

---

<div class="post-metadata">

**Author:** ![slindberg](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/slindberg/32/15091_2.png) [@slindberg](https://discuss.emberjs.com/u/slindberg)\
**Post date:** [February 9, 2015, 11:10pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/7 "2015-02-09T23:10:30Z")

</div>

With the upcoming deprecation of `Ember.ArrayController` and therefore item controllers, it looks like @joelataylor’s approach of using components to render table rows is the way to go. This works well until you want to make the entire row a clickable link. In the past (currently), using item controllers allows for rendering partials that don’t insert extra elements into the DOM, so this was easy:

`app/templates/thing/index.hbs`

```handlebars
<table>
  <tbody>
    {{#each thing in things}}
      {{partial "thing/row"}}
    {{/each}}
  </tbody>
</table>

```

`app/templates/thing/row.hbs`

```handlebars
{{#link-to "thing.edit" thing tagName="tr"}}
  <td>{{thing.name}}</td>
{{/tr}}

```

See [this github issue](https://github.com/emberjs/ember.js/issues/2779)

Unfortunately taking the component approach, this breaks down since components insert their own element (the one that the `link-to` was in the partial):

`app/routes/thing/index.hbs`

```javascript
export default Ember.Route.extend({
  actions: {
    transitionToEditRoute: function(thing) {
      this.transitionTo('thing.edit', thing);
    }
  }
});

```

`app/templates/thing/index.hbs`

```handlebars
<table>
  <tbody>
    {{#each thing in things}}
      {{thing-row model=thing action="transitionToEditRoute"}}
    {{/each}}
  </tbody>
</table>

```

`app/components/thing-row.js`

```javascript
export default Ember.Component.extend({
  tagName: 'tr'

  click: function() {
    this.sendAction('action', this.get('model'));
  }
});

```

`app/templates/components/thing-row.hbs`

```handlebars
{{! this is implicitly wrapped in a tag that we cannot control from the template }}
<td>{{model.name}}</td>

```

Although the item controller / partial approach always seemed like a bit of a hack to me, using the component approach and having to create an action whose sole purpose is to call `this.transitionTo(...)` in a route seems even worse. It is arguably more idiomatic / easier to reason about, which is a good thing, but the router action still feels wrong. Does anyone else have a better solution?

---

<div class="post-metadata">

**Author:** ![jcbvm](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/jcbvm/32/11865_2.png) [@jcbvm](https://discuss.emberjs.com/u/jcbvm)\
**Post date:** [April 2, 2015, 8:17pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/8 "2015-04-02T20:17:12Z")

</div>

I had the same problem, and I absolutely agree with @slindberg about the fact that it feels wrong to define a transitionTo in the route. Currently I’m using another solution which also doesn’t feel right, but feels better than the solutions mentioned. Instead of using a row component I now use a tbody component. This component holds a list of all the table rows wrapped in a object. This object has the same purpose as an ItemController, namely to wrap the content in an object with extra properties. By defining the component as a tbody element I’m still able to define a row as a link.

I’m still looking for a better solution though, because it requires a lot of code decoupling and it seems that it is just easier to define all properties on the model itself, so I don’t even need a component at all for the tables.

---

<div class="post-metadata">

**Author:** ![slindberg](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/slindberg/32/15091_2.png) [@slindberg](https://discuss.emberjs.com/u/slindberg)\
**Post date:** [April 15, 2015, 5:30pm UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/9 "2015-04-15T17:30:02Z")

</div>

To follow up: I believe the [element/fragment RFC](https://github.com/ef4/rfcs/blob/element-and-fragment/active/0000-element-and-fragment.md) will address this issue, e.g.

`app/templates/thing/index.hbs`

```handlebars
<table>
  <tbody>
    {{#each thing in things}}
      {{thing-row model=thing}}
    {{/each}}
  </tbody>
</table>

```

`app/components/thing-row.js`

```javascript
export default Ember.Fragment.extend({
  // item controller logic
});

```

`app/templates/thing-row.hbs`

```handlebars
<fragment>
  {{#link-to "thing.edit" model tagName="tr"}}
    <td>{{model.name}}</td>
  {{/tr}}
</fragment>

```

---

<div class="post-metadata">

**Author:** ![Sir\_Branson](https://avatars.discourse-cdn.com/v4/letter/s/e0b2c6/32.png) [@Sir\_Branson](https://discuss.emberjs.com/u/Sir_Branson)\
**Post date:** [June 27, 2015, 7:46am UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/10 "2015-06-27T07:46:02Z")

</div>

thanks, this really helped me out

---

<div class="post-metadata">

**Author:** ![Sir\_Branson](https://avatars.discourse-cdn.com/v4/letter/s/e0b2c6/32.png) [@Sir\_Branson](https://discuss.emberjs.com/u/Sir_Branson)\
**Post date:** [June 27, 2015, 7:48am UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/11 "2015-06-27T07:48:58Z")

</div>

use `tagName: 'tr',` and inside the component just have td tags, works

---

<div class="post-metadata">

**Author:** ![serjpetrenko](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/serjpetrenko/32/16182_2.png) [@serjpetrenko](https://discuss.emberjs.com/u/serjpetrenko)\
**Post date:** [October 12, 2018, 7:05am UTC](https://discuss.emberjs.com/t/how-to-use-components-for-a-table-row/5134/13 "2018-10-12T07:05:50Z")

</div>

In 3.4 version of Ember i used `tagName: ''` inside component.js to render separate component with tbody
