0

I'm looking for some assistance in setting up a table view to be able to sort merged columns separately. At a high level I have the following view table:

First Name Last Name Age/Weight^
Ken Davidson Age: 42
Weight: 200

I have all three columns sortable, except that the third column only sorts by Age, even though it has two possible sort options. Clicking the Age/Weight will only sort by Age, there is no way that I can see to make it sortable by either Age or Weight.

I found a couple links here that don't seem overly optimistic, but I'm hoping that things have changed:

Edit

The more I look into this, the more I'm starting to think that the only way to do this is by providing a custom template views-view-table--custom-view-name.html.twig and would need to overwrite the one section:

      <tr>
        {% for key, column in header %}
          {% if column.default_classes %}
            {%
              set column_classes = [
                'views-field',
                'views-field-' ~ fields[key],
              ]
            %}
          {% endif %}
          <th{{ column.attributes.addClass(column_classes).setAttribute('scope', 'col') }}>
            <div class="th-wrap">
              {%- if column.wrapper_element -%}
                <{{ column.wrapper_element }}>
                  {% if column.title == 'sort by Age/Weight' %}
                    <!-- Add two links hardcoding the URL appropriately -->
                  {% else %}
                    {%- if column.url -%}
                    <a href="{{ column.url }}" title="{{ column.title }}">{{ column.content }}{{ column.sort_indicator }}</a>
                  {%- else -%}
                    {{ column.content }}{{ column.sort_indicator }}
                  {%- endif -%}
                </{{ column.wrapper_element }}>                    
                  {% endif %}                  
              {%- else -%}
                {%- if column.url -%}
                  <a href="{{ column.url }}" title="{{ column.title }}">{{ column.content }}{{ column.sort_indicator }}</a>
                {%- else -%}
                  {{- column.content }}{{ column.sort_indicator }}
                {%- endif -%}
              {%- endif -%}
            </div>
          </th>
        {% endfor %}
      </tr>

Before I follow this path, does it seem like an optimal solution? The issue here is that I would lose the ability to display the sort indicator, since the column is still directly related to Age/Weight (which is just Age) instead of the individual columns.

Is there a global variable available in the views-view-table renderer that I would be able to check for the actual sort column? Is the URL available for parsing?

1 Answer 1

0

I was able to get this working - in the most Drupal best practice way I could think of. If this is way off, I'd love some guidance on how to do this properly, but for those looking for the same:

I added a theme preprocessor to update the table $variables with the sort/order at the highest level:

function sc_preprocess_views_view_table(&$variables) {  
  $view = $variables['view'];
  $handler = $view->style_plugin;
  $variables['sorting'] = array(
    'active' => $handler->active, 
    'order' => $handler->order
  );
}

The twig file was updated with:

// views-view-table--custom-view--page.html.twig
{% if column.title == 'sort by Age/Weight' %}
  <a href="{{ sc_column_sort_url('field_hfs_age', sorting) }}" title="Sort by age">age</a>
  {% if sorting['active'] == 'field_hfs_age' %}
    {{ sc_column_sort_indicator(sorting['order']) }}
  {% endif %} /
  
  <a href="{{ sc_column_sort_url('field_hfs_weight', sorting) }}" title="Sort by weight">weight</a>
  {% if sorting['active'] == 'field_hfs_weight' %}
    {{ sc_column_sort_indicator(sorting['order']) }}
  {% endif %}
{% else %}
  // Original code
{% endif %}

And two custom Twig Functions were created

  /**
   * Provides common functionality for building the custom column sort URL required.
   * @param $name the name of the current field
   * @param $sorting the associated array of the current sort
   */
  public function scTableSortUrl($name, $sorting) {
    $nextSort = ($sorting['active'] == $name && $sorting['order'] == 'asc' ? 'desc' : 'asc');
    return "?order={$name}&sort={$nextSort}";
  }

  /**
   * Display the table sort indicator of the current custom table.   I'm sure this exists somehwere
   * else, but I can't find it.
   * @param $initial the initial sort order [asc | desc]
   */
  public function scTableSortIndicator($initial) {
    return [
      '#theme' => 'tablesort_indicator',
      '#style' => $initial,
    ];
  }

https://www.hashbangcode.com/article/drupal-9-creating-custom-twig-functions-and-filters for reference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.