Addepar / ember-table

https://opensource.addepar.com/ember-table/
Other
1.69k stars 353 forks source link

Programatic row selection seems broken? #823

Open kpfefferle opened 4 years ago

kpfefferle commented 4 years ago

I have an ember-table where I need to compute the selected row based off of the current route (because the table serves as the master in a master/detail view layout). When rendering a row's detail route, I want that row to be selected. I was doing this in a different part of the app successfully before, but that part of the app has moved away from that layout since, so I'm unsure when it stopped working.

Here's what I'm doing in the component that renders my table to compute the selection as the row which matches the currently rendered detail route (which renders in an {{outlet}} alongside the Orders ember-table:

export default class OrdersTable extends Component {
  @service router;

  // ...

  get selection() {
    let { rows } = this;
    let { currentRoute, currentRouteName } = this.router;
    if (currentRouteName !== 'orders.order') {
      return undefined;
    }
    let orderId = currentRoute.params.orderId;
    return rows.find(row => row.id === orderId);
  }

  // ...

  @action
  onSelect(selection) {
    this.router.transitionTo('orders.order', selection.id);
  }
}

In the template, I pass this.selection and this.onSelect to t.body:

<EmberTable as |t|>
  <t.head @columns={{this.columns}} />
  <t.body
    @checkboxSelectionMode="none"
    @onSelect={{this.onSelect}}
    @rows={{this.rows}}
    @rowSelectionMode="single"
    @selection={{this.selection}}
  />
</EmberTable>

Though this.selection returns the row object that I would expect, ember-table does not mark the matching table row with the .is-selected class 😬

kpfefferle commented 4 years ago

I have a couple things I've tried that I'll document as separate comments for clarity...

Using the example from the ember-table docs, I tried this (with the JS getter above commented out):

<EmberTable as |t|>
  <t.head @columns={{this.columns}} />
  <t.body
    @checkboxSelectionMode="none"
    @onSelect={{action (mut this.selection)}}
    @rows={{this.rows}}
    @rowSelectionMode="single"
    @selection={{this.selection}}
  />
</EmberTable>

The result there is working select behavior for the row (though it clearly doesn't transition to the route as is the desired app behavior).

kpfefferle commented 4 years ago

Given the above works, I wondered if setting this.selection as part of my custom onSelect action would work for initial interaction (though it would not be expected to work correctly for direct load of the details route)...

I keep the template the same as original:

<EmberTable as |t|>
  <t.head @columns={{this.columns}} />
  <t.body
    @checkboxSelectionMode="none"
    @onSelect={{this.onSelect}}
    @rows={{this.rows}}
    @rowSelectionMode="single"
    @selection={{this.selection}}
  />
</EmberTable>

...but I change the JS to save this.selection (which then gets consumed by the template):

export default class OrdersTable extends Component {
  @service router;

  // ...

  @tracked selection;

  // ...

  @action
  onSelect(selection) {
    this.selection = selection;
  }
}

This also works, but once I add in the route transition, it stops working:

export default class OrdersTable extends Component {
  @service router;

  // ...

  @tracked selection;

  // ...

  @action
  onSelect(selection) {
    this.selection = selection;
    this.router.transitionTo('orders.order', selection.id);
  }
}

Though this seems like it should be doing the same thing re: this.selection, ember-table no longer renders the row as selected 🤔

aemc commented 2 years ago

Were you able to get this working @kpfefferle ? I did something similar and passed a custom onSelect method and I find that the row does not get the high-light class.