Page MenuHomePhabricator

Table: handle sorting + row selection
Closed, ResolvedPublic3 Estimated Story Points

Description

Background

Currently, data for table rows can be passed into the Table component via the data prop. This must be an array of objects, with each object being the data for a single row.

However, this will not work for a table that needs both row selection and sorting. The Table component and its parent keep track of which rows are selected by referencing the selected rows' indexes in the data prop. If the data prop changes due to sorting, the indexes no longer tell us which rows should be selected.

Solution

Dev users who want both sorting and row selection will be required to add a property to each TableRow with a unique ID, that can be used (if present) within the Table code to identify which rows are selected (instead of the row's index within the data prop array). As Roan suggests in the comments, we can use a symbol for this special row property.


Acceptance criteria

  • Decide how to handle this
  • Implement the solution
  • Add/update unit tests as needed
  • Add a demo to the Sandbox showing how this works
  • Add a note to the docs site in the "row selection" demo section discussing how to pass in data when you want both sorting and row selection

Related Objects

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

If data was an object, then how would you express the order of the rows, much less sort them? Objects in JS seem to be ordered in practice (if you iterate over an object it seems to always return the keys in the order they were defined), but I don't think they are in theory, and they're not designed with ordering in mind, so it's not easy to construct an object with the keys in a certain order and pretty hard to reorder the keys when sorting. You could add another prop that's an array with the identifiers in order, but that would make things even messier.

I can't believe I didn't think about this before, but I think I have a good solution: do approach #1 (special property in each row), but make the special property an ES6 Symbol instead of a string. That would look like this:

// In constants.ts
export const TableRowIdentifier = Symbol( 'CdxTableRowIdentifier' );

// In types.ts, change the type of TableRow to allow this new symbol as a key
export type TableRow = Record<string | typeof TableRowIdentifier, any>;

// In Table.vue, you'd access the identifier of a row like this:
row[ TableRowIdentifier ]

Users would define their data like this:

const data = [
    { [TableRowIdentifier]: 'Q123'  title: 'Georgia', description: 'Country in Central Asia' },
    { [TableRowIdentifier]: 'Q456', title: 'Georgia', description: 'State in the United States' }
];

This avoids collisions because a Symbol is not equal to anything except itself (not even to another Symbol with the same name), so the only way you can get it is by importing it from constants.ts. Another useful property of Symbols is that Symbol keys are skipped when iterating over an object: if you did a v-for over data[0] above, that loop would only see the 'title' and 'description' keys, the identifier wouldn't be visible to it (this doesn't matter for us right now because we never actually iterate over row objects, we iterate over the columns array instead).

If you don't want to use a Symbol, then the next best suggestion I have is #1 but with a special key that's clearly special, maybe prefixed with an underscore like _id or _cdxTableRowId.

Change #1029542 had a related patch set uploaded (by Anne Tomasevich; author: Anne Tomasevich):

[design/codex@main] Table: Enable sorting with row selection

https://gerrit.wikimedia.org/r/1029542

Thanks for the good idea, @Catrope! A Symbol is probably the Right Thing To Do. I've opened a patch implementing this, and the updates needed within Table were minimal, which is nice. TypeScript doesn't like TableRowIdentifier being used as an index type in the template for some reason (but it's fine with it in the script), so there's still some refinement to do, but I wanted to get a patch up so we could see what the usage looks like.

AnneT changed the task status from Open to In Progress.May 9 2024, 5:57 PM
AnneT updated the task description. (Show Details)

Change #1029542 merged by jenkins-bot:

[design/codex@main] Table: Enable sorting with row selection

https://gerrit.wikimedia.org/r/1029542

AnneT updated the task description. (Show Details)

Change #1032095 had a related patch set uploaded (by VolkerE; author: VolkerE):

[mediawiki/core@master] Update Codex from 1.5.0 to 1.6.0

https://gerrit.wikimedia.org/r/1032095

Change #1032095 merged by jenkins-bot:

[mediawiki/core@master] Update Codex from 1.5.0 to 1.6.0

https://gerrit.wikimedia.org/r/1032095