Atlaskit Dynamic Table component not sorting as expected

Either the documentation is a little under cooked or there may be a defect in the dynamic-table component as i have plain-text columns which do not sort by Asc or Desc like one would expect to happen.

When I compare the underlying structure of my heading and rows, I’m not seeing anything obviously different, content is a string for the Name, Key and Project Type columns.

In another table it doesn’t even attempt to sort, at least this one is doing that but the sorting is a little odd.

The docs don’t really explain much about how this feature is meant to work or any caveats / gotchas to know about.

See below:

image

Hi @murrays - would you mind sharing your code, or at least your table component initialization? There are two types of dynamic tables – stateful, and stateless – perhaps you’re using stateless, which does not allow for sorting/reordering.

See examples here: https://ak-mk-2-prod.netlify.com/mk-2/packages/elements/dynamic-table

I believe the stateless table requires importing it specifically, i’m importing the default which from the documentation is stateful

import DynamicTable from '@atlaskit/dynamic-table';

// . . .

<DynamicTable
     isFixedSize
     head={logic.generateHeadingData()}
     rows={logic.generateRowData()}
/>

// The heading functions return an object that looks like:
const head = {
    cells: [
        {
            key: 'icon',
            content: '',
            width: 4,
        },
        {
            key: 'name',
            content: 'Name',
            isSortable: true,
            shouldTruncate: true,
            width: 38,
        },
        {
            key: 'key',
            content: 'Key',
            isSortable: true,
            width: 12,
        },
};

return head;

// Row data is an array of objects - each having a "cells" property which is an array of fields for that row set out like so:

// . . .
cells: [
    {
        key: 'icon',
        content: (
            <img src={store[rowStoreName].smallAvatarUrl} />
        ),
    },
    {
        key: 'name',
        content: store[rowStoreName].name,
    },
    {
        key: 'key',
        content: store[rowStoreName].key,
    },
]

@nmansilla have you heard anything or seen anything that could indicate why sorting is not working as expected?

Worth mentioning i spose that in the screenshot provided it depicts the table being sorted with a darkened Down arrow, whereas in a stateless version, the arrows never change.

1 Like

Worked out the source of why the sorting isn’t working as expected: Turns out those keys for the row need to be dynamically generated and unique per row.

Name Key
{ key: ‘name1’, content: ‘Name 1’ } { key: ‘key1’, content: ‘key1’ }
{ key: ‘name2’, content: ‘Name 2’ } { key: ‘key2’, content: ‘key2’ }

This lets the name column sort using the unique key per row for Name (name1, name2) and the same for the Key column

The docs might benefit from clarifying this as the way they read to me gave the impression that the key for a row should match the key of the associated column, but when looking into the source code it became clear that this was not the usage case for the key properties.

1 Like

@murrays Thanks for the feedback.

So whilst the above resolves the initial problem with sorting, due to the package using Array indexes for the React keys, what happens is that references to a specific control button on a row get broken when you sort the table as React thinks the button associated with a row is somewhere else in the column to where it should be.

So I guess what that means is that dynamic tables in their current form are only suitable for displaying static content.

I got around this by using the stateless version of the tables and handling all the sorting functionality prior to passing in the sorted arrays of items for display.

Hope this helps others.

So, I’ve not had a similar problem to yours; I’ve got a couple of Toggle controls in my table row, and they seem to stay associated with the object they’re meant to, even after sorting by another column changes the order of the rows. This may be because I pass the needed data to uniquely identify the particular piece of data into the onChange handler of the Toggle controls. I’m curious how you’re adding control buttons to a given row.

Hi I am new in Atlaskit/reactjs world. trying to use table component with sorting/filtering and pagination. Is there any tutorial available online how to use Atlaskit dynamic table into my code? Also how can i perform data changes to make dynamic table work?

Please help
Thanks

@jcarter The stateful dynamic table uses the Array index for keys when mapping rows which goes against the recommended warnings provided by React for the reason that can be observed when you have content in table rows that gets updated by setState in the parent. i.e. an async toggle that get’s it’s current state updated by the parent’s store once the associated action completes.

In the above scenario, you’ll find that the store subscription bindings for the toggle are linked to the Row component key… so sorting shifts the static content to a new index, but that toggle remains on the incorrect row creating a mess. this is why the alternative is to use the stateless version, take full control of sorting and ensure that each row of data is a single component so changing the index keeps that data together on the same row.

An added benefit is that it provides control for more appropriate sorting techniques on things like dates or numbers which would have otherwise been sorted using a blanket alphabetical ASC / DESC approach, which isn’t desirable in most cases for non-alphabetical data.

@atifchughtai If you just want to display static text then use Stateful version (default export) if you want to have complex controls nested in table rows use StatelessDynamicTable (named export) and roll out custom handling for sorting if required.

In either case, you will want the data that drives table rows to be generated by a function that takes a Store property as a parameter. This should take place inline inside the render() {} function so updating the store data will trigger a setState() which in turn will re-render the rows showing new data for them.

This assumes using connected components to a store system, if you are using the new ContextAPI or manually calling setState() with this.state() I would guess it’s a very small application and you might find manually driving setState() calls with functionality to be a fine substitution for Actions (redux or mobx)

I’m still unable to change arrows up down in stateless version. Any solutions for this? I see this library has very poor documentation. And very difficult to do customization.

2 Likes

Agree, the documentation is really poor and quite messy

2 Likes