I think it would be great to have a sort option in TableField (e.g. sort by column A or column B, etc.).

Just throwing that out there. :)

Issue fork tablefield-1491584

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Mołot’s picture

Issue summary: View changes

http://tablesorter.com/docs/ - this jQuery plugin might help, if all you want is to sort on display.

lolandese’s picture

Version: 7.x-2.x-dev » 7.x-3.x-dev
dedicated_hobby_coder’s picture

lolandese’s picture

Excellent suggestion and IMHO the way to go.

Needed is a display option (checkbox) 'Sortable' that adds the class 'tablesorter' to the table, probably through $variables['attributes']. Note that we have a patch currently under review that swaps the core theme_table() with the custom theme_tablefield(). That was needed to make vertical headers possible (first column instead of first row). See #2058325: [D7]: Allow to have the first column as header instead of first row.

NOTE: The sort functionality should be disabled in case we only have a vertical header.

Implementation is however similar for both theme functions so a patch can be provided anyhow. Feel free to do so.

We noticed Tablesorter offers some styling. Best is to stick with System's Default and let the implemented theme take care of the styling. To look into how various core themes deal with that. In theme.inc we have the function theme_tablesort_indicator($variables) that might come handy.

lolandese’s picture

CSS start for the sort arrows to indicate the column is sortable:

td.row_0.col_1 {
    position: relative;
}

td.row_0.col_1:after {
    content: '';
    /* background: red; */
    width: 6px;
    height: 1px;
    position: absolute;
    display: block;
    right: 0;
    top: 24%;
    border-top: none;
    border-bottom: 7px solid red;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
}

.. or something like http://stackoverflow.com/a/22222257/523688.

Alternatively using a symbol plus text. See http://ux.stackexchange.com/a/80233.

lolandese’s picture

Status: Active » Needs review
StatusFileSize
new7.55 KB

  • lolandese committed 4076591 on 7.x-3.x
    Issue #1491584 by lolandese: Sort option would be wonderful
    
lolandese’s picture

Status: Needs review » Fixed
lolandese’s picture

Status: Fixed » Needs work

We probably could improve it by avoiding inline styling and use the tablesorter class at least for the mouse pointer on hover.

Not sure if we can do the same for the title (tooltip).

lolandese’s picture

Status: Needs work » Needs review
StatusFileSize
new2.91 KB

#9 plus disable the sort option in the settings if we only have a vertical header.

  • lolandese committed d8dfc2b on 7.x-3.x
    Issue #1491584 by lolandese: A better sort option.
    
lolandese’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

lolandese’s picture

Status: Closed (fixed) » Patch (to be ported)
Parent issue: » #2189203: D8 port (from the existing 7.x-3.x to a new 8.x-3.x)
lolandese’s picture

Issue tags: +LutskGSW18
lolandese’s picture

Version: 7.x-3.x-dev » 8.x-2.x-dev

Port 7.x-3.x features to a new 8.x-3.x version (to be created).

douggreen’s picture

StatusFileSize
new5.39 KB

Attached patch for D8/9. This is a re-implementation, rather than a port. A couple of notes:

* A moduleExists() check before adding a class is unnecessary IMO so I didn't add it.
* The sortable column defaults to 1 if tablesorter is enabled, otherwise it's 0.
* No additional styling is done, tablesorter seems to style just fine to me.

lolandese’s picture

Status: Patch (to be ported) » Needs review

Changing status to trigger the test on the supplied patch.

jayhuskins’s picture

StatusFileSize
new5.39 KB

hook_update_8002 is used in another patch, so this patch updates the number to 8010 to remove the conflict.

douggreen’s picture

We shouldn't renumber this way, update's should be sequential, if there's a conflict between two patches being applied, usually you copy the patch locally and apply your local patch. I'm removing #19 and restoring #17 as the primary patch for this reason. I'm leaving #10 because that's an alternative solution.

bala.addweb’s picture

StatusFileSize
new3.61 KB

sort-table-on-header-click.patch

erutan’s picture

The patches in this issue queue no longer work in Drupal 10.3.10.

#21 applied cleanly, but there were no options for sortable tables and no sortable tables automatically.

#19 popped up the following error multiple times when loading the entity with the field I want to sort in the admin edit interface:

Warning: Undefined property: stdClass::$field_tr_receiver_test_data_sortable in Drupal\Core\Entity\Sql\SqlContentEntityStorage->loadFromDedicatedTables() (line 1269 of /app/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php)
#0 /app/web/core/includes/bootstrap.inc(166): _drupal_error_handler_real(2, 'Undefined prope...', '/app/web/core/l...', 1269)
#1 /app/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1269): _drupal_error_handler(2, 'Undefined prope...', '/app/web/core/l...', 1269)
#2 /app/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(503): Drupal\Core\Entity\Sql\SqlContentEntityStorage->loadFromDedicatedTables(Array, false)
#3 /app/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(428): Drupal\Core\Entity\Sql\SqlContentEntityStorage->mapFromStorageRecords(Array)
#4 /app/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(394): Drupal\Core\Entity\Sql\SqlContentEntityStorage->getFromStorage(Array)
#5 /app/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(312): Drupal\Core\Entity\Sql\SqlContentEntityStorage->doLoadMultiple(Array)
#6 /app/web/core/modules/views/src/Plugin/views/query/Sql.php(1632): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array)
#7 /app/web/core/modules/views/src/Plugin/views/query/Sql.php(1557): Drupal\views\Plugin\views\query\Sql->loadEntities(Array)
#8 /app/web/core/modules/views/src/ViewExecutable.php(1486): Drupal\views\Plugin\views\query\Sql->execute(Object(Drupal\views\ViewExecutable))
#9 /app/web/core/modules/views/src/ViewExecutable.php(1514): Drupal\views\ViewExecutable->execute(NULL)
#10 /app/web/core/modules/views/src/Plugin/views/display/Page.php(201): Drupal\views\ViewExecutable->render()
#11 /app/web/core/modules/views/src/ViewExecutable.php(1690): Drupal\views\Plugin\views\display\Page->execute()
#12 /app/web/core/modules/views/src/Element/View.php(81): Drupal\views\ViewExecutable->executeDisplay('storage_page_li...', Array)
#13 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array)
#14 /app/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(113): call_user_func_array(Array, Array)
#15 /app/web/core/lib/Drupal/Core/Render/Renderer.php(870): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'exception', 'Drupal\\Core\\Ren...')
#16 /app/web/core/lib/Drupal/Core/Render/Renderer.php(432): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array)
#17 /app/web/core/lib/Drupal/Core/Render/Renderer.php(248): Drupal\Core\Render\Renderer->doRender(Array, false)
#18 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(238): Drupal\Core\Render\Renderer->render(Array, false)
#19 /app/web/core/lib/Drupal/Core/Render/Renderer.php(638): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
#20 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(231): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#21 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(128): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#22 /app/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#23 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#24 /app/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#25 /app/vendor/symfony/http-kernel/HttpKernel.php(186): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#26 /app/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#27 /app/web/modules/contrib/redirect_after_login/src/RedirectMiddleware.php(44): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /app/web/core/lib/Drupal/Core/StackMiddleware/Session.php(53): Drupal\redirect_after_login\RedirectMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /app/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#31 /app/web/core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#32 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#33 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#34 /app/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#35 /app/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#36 /app/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#37 /app/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#38 /app/web/core/lib/Drupal/Core/DrupalKernel.php(741): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#39 /app/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#40 {main}

Furthermore if I go to edit a tablefield @ /admin/structure/storage_types/foo/edit/fields/ I get a whitescreen with the following:

The website encountered an unexpected error. Try again later.

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'foo_bar_sortable' in 'where clause': SELECT 1 AS "expression" FROM "storage_revision__foo_bar" "t" WHERE ("foo_bar_value" IS NOT NULL) OR ("foo_bar_format" IS NOT NULL) OR ("foo_bar_caption" IS NOT NULL) OR ("foo_bar_sortable" IS NOT NULL) LIMIT 1 OFFSET 0; Array ( ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage->countFieldData() (line 1794 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
erutan’s picture

Status: Needs review » Needs work

#19 is loading the JS lib, tr/td have a different background color and there are grey triangles to use as sort toggles, but it is not interactive.

tim-diels’s picture

Patch from #17 and patch from #21 are quiet different.

What is the expected approach here to have table sorting added? I see the module uses the Tablesorter module for the 7.x version and that was the same as with patch from #17 but the person in #21 decided on itself that they wanted to go a different approach without explaining why.

I'm more of a fan of using the Tablesorter module as this is also what the maintainer proposed on using. So can we have a concensus on using this approach?

tim-diels’s picture

Status: Needs work » Needs review

Added patch from #17 to the latest codebase so going to hide all other patches.
I think a nice follow up would be a setting to allow to specify what columns should be sortable as the library supports this. But that could be a separate issue so this can go in as is and the change is not to big.

tim-diels’s picture

tim-diels’s picture

Status: Needs review » Needs work

The code works for me, only no visual for sorting. Is this something that is needed for the tablesorter module itself or it could be added here as done in the 7.x branch. The tablesorter said is is something the theme should fix. So maybe just some documentation and just the cursor set to pointer?

Setting to needs work for the css.

tim-diels’s picture

We can also suggest installing the tablesorter in a composer file...

erutan’s picture

Would it be more appropriate if the functionality of this patch was a submodule included with TableField?

If someone installs TableField Sort (or some other name) then we can have tablesorter installed as a dependency. This wouldn't impact people that don't want the functionality while making it simpler for those that do.

There isn't a stable build of tablesorter for D8+, but the 2.0 branch is up to RC2 and around a third of the people using the module are running that branch.

tim-diels’s picture

Status: Needs work » Needs review

@erutan I do like your suggestion. But can't put time in this now to completely refactor it to be a submodule. If a maintainer could assist in deciding what would be the best approach, then we can see what we need to do to get this finished.

I understand that there is no proper release for tablesorter. I'll try to get some time to get a proper release there. I would suggest not yet adding this to a release until there is a proper release of tablesorter.

The CSS I did not add as I think this is not necessary as a theme could handle this? Any opinions on that?

Setting this to needs review as in my eyes it seems complete now.

erutan’s picture

Any thoughts on this from the more senior maintainers? I think it's be great functionality to get in.

I take a look at the CSS side of things. :)

liam morland’s picture

Version: 8.x-2.x-dev » 3.0.x-dev
Status: Needs review » Needs work
Issue tags: +Needs reroll

Please rebase on 3.0.x.

prem suthar made their first commit to this issue’s fork.

prem suthar changed the visibility of the branch 1491584-sort-option-would to hidden.

carlos romero made their first commit to this issue’s fork.

carlos romero’s picture

Reroll patch for 2.5 version, mr done

carlos romero’s picture

Status: Needs work » Needs review
liam morland’s picture

Status: Needs review » Needs work

I don't think there is going to be any more development of 8.x-2.x. Merge request 56 is for 3.0.x. This version needs tests to all pass.