Addepar / ember-table

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

sorting and queryParams #761

Open basz opened 5 years ago

basz commented 5 years ago

Hi,

I'm looking for a way to have paging and sorting accessible via query params (for navigation purposes (back button)). For paging I got this working now, but the sorting logic is hardcoded with a click handler which (seems to) means I cannot easily use a link-to helper with its query property in a custom header template.

What would be the recommended manner to achieve sorting via query params?

<t.head
    @columns={{this.columns}}
    @sorts={{this.sorts}}
    @onUpdateSorts={{action "onUpdateSorts"}} as |h|>

    <h.row as |r|>
      <r.cell as |columnValue columnMeta|>
        {{#if columnMeta.isSortable}}
          <EmberTh::SortIndicator @columnMeta={{columnMeta}} />
          <LinkTo @query={{hash sort=columnValue.valuePath}}>{{columnValue.name}}</LinkTo>
        {{/if}}

        <EmberTh::ResizeHandle @columnMeta={{columnMeta}} />
      </r.cell>
    </h.row>
</t.head>
basz commented 3 years ago

To answer myself; just use an onUpdateSorts action and transition into a new route.

@action
  onUpdateSorts(sorts) {
    this.router.transitionTo(this.router.currentRouteName, { queryParams: { page: 1, sort: Sorting.toQueryValue(sorts) } });
  }
kpfefferle commented 2 years ago

@basz The approach I've used with much success is to persist the value for @sorts on the Controller like any other query param. I additionally implement a custom get/set to serialize the sorts array to a JSON string for the QP and deserialize it back to an array of objects for ember-table. Here's an example (in TypeScript) of the base Controller class that I use for Controllers that will persist an ember-table sorts to QP:

import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { EmberTableSort } from 'ember-table';

export default class extends Controller {
  queryParams = ['sorts'];
  @tracked sorts: string | null = null;

  get sortsValue(): EmberTableSort[] | undefined {
    let { sorts } = this;
    if (!sorts) {
      return undefined;
    }

    return JSON.parse(sorts) as EmberTableSort[];
  }
  set sortsValue(value: EmberTableSort[] | undefined) {
    this.sorts = value?.length ? JSON.stringify(value) : null;
  }

  @action updateSorts(sorts?: EmberTableSort[]): void {
    this.sortsValue = sorts;
  }
}