How to provide a link to a specific tab?

Created on 15 August 2023, over 1 year ago
Updated 16 August 2023, over 1 year ago

Problem/Motivation

Wasn't sure if this was as a duplicate: #3221665: Goto another tab .

Most tab modules provide the ability to permalink a specific tab. But providing the anchor in the url has no impact on the default tab.

My full use case is I want to set default tab in order of:

  1. anchor in url
  2. cookie set when selecting a tab (js in custom module)
  3. default defined in Layout Builder section config (part of this module)

Part 2 of this can be accomplished by hook_js_settings_alter() and setting $settings['lb_tabs_tabs']['lb-tabs-tabs']['active'] to the required tab "position" (this is made more complicated by the ability to hide empty tabs: 📌 Hide accordion if contained fields are empty/have no content Active as we need to set active as the position of the tab not the id of the tab as it may change from page (node) to page depending on which tabs are hidden).

Part 1 is trickiest in that the anchor is not known by the server, so the js alter hook cannot be used. This must be done in js.

I likely need to patch the tabs.js file to allow evaluating the anchor to override the "active" tab (but also has to take hidden tabs into account).

Any thoughts?

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Feature request
Status

Active

Version

3.0

Component

Code

Created by

🇨🇦Canada liquidcms

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @liquidcms
  • 🇨🇦Canada liquidcms

    The attached patch modifies the tabs.js (would need to be repeated for accordians.js) to set the tab based on anchor in url if it is set.

    Also, once this feature is available then going to a link with the anchor will, of course, try to have the page go to the anchor. This causes it to jump around a bit. Even without this though i think you would see the page with all the tab content until the jq tabs code kicks in and hides the unselected tabs. To clean all this up I added css to the tabs.css to hide all the tab content (this is in this patch but not the required class added to the div wrapping the content (which is required). And then in this tabs.js change I included code to remove that "hide tabs" class on page load. This gives a much cleaner result while also supporting the ability to go to a specific tab.

    Also, outside this patch, but required for all of this, in my theme file i added the following preprocess function to base tab ids on tab weight as opposed to position. So tabs will be lb-tabs-tabs-0, 1, 3 instead of 0, 1, 2 if the 3rd tab is empty and therefore hidden ( 📌 Hide accordion if contained fields are empty/have no content Active ). I am not sure if there is a use case where marking by position rather than weight would make more sense but i struggled to come up with one.

    To summarize:
    - this patch to modify tabs.css and tabs.js

    - preprocess function to make weights available in template:

    function mytheme_preprocess_lb_tabs_tabs(&$variables) {
      $variables['content']['weight'] = [];
      foreach ($variables['content']['content_blocks'] as $block) {
        if (isset($block['#weight'])) {
          $variables['content']['weight'][] = $block['#weight'];
        }
      }
    }

    - overridden template to use this for tab content id and href to tab A tags:
    {{ settings.dom_id }}-{{content.weight[loop.index0]}}

  • 🇨🇦Canada liquidcms

    Not entirely part of this feature request but mention in the OP, this is how we set default tab as last selected (cookie):

        $('.page-node-type-mynode ul.lb-tabs__options-list li').click(function() {
          cookies.set('mynode-default_tab', $(this).find('a').attr('href'));
        });

    and then to pass active tab to tabs.js:

    /*
     * Set default tab based on:
     * - anchor in URL if defined (included in tabs.js)
     * - cookie if set
     * - LB section setting
     */
    function my_custom_js_settings_alter(array &$settings, \Drupal\Core\Asset\AttachedAssetsInterface $assets) {
      if (isset($settings['lb_tabs_tabs']['lb-tabs-tabs'])) {
    
        $node = \Drupal::routeMatch()->getParameter('node');
    
        // Set tab by cookie if set.
        $stack_service = \Drupal::service('request_stack');
        $cookie = $stack_service->getCurrentRequest()->cookies->get('mynode-default_tab');
        if ($cookie) {
          $id = str_replace('#lb-tabs-tabs-', '', $cookie);
          $active = $id;
    
          $active = figure_out_position_of_tab($node, $id);   // some function to determine empty tabs and reduce $active if any empty.
    
          $settings['lb_tabs_tabs']['lb-tabs-tabs']['active'] = $active;
        }
      }
    }
  • 🇨🇦Canada liquidcms

    Oops, typo in the patch above.

Production build 0.71.5 2024