cdm
cdm

Reputation: 799

django tables2 display sort arrows on header

I'm using django tables2, and I think it would be useful to have up and down arrows on header columns to indicate the current sorting order, especially when the default sort is on a column other than the first.

Tried playing with CSS but no luck, any suggestions or examples on how to do this?

Upvotes: 3

Views: 1939

Answers (3)

Frohus
Frohus

Reputation: 7

I know it's an old question but I stumbled on this issue as I wanted to use SVG icons in the orderable headers and change their colours which I couldn't do with CSS when icon were added to ::after selector. I already had a customised table template so I did like below:

<th {{ column.attrs.th.as_html }}>
    {% if column.orderable %}
        <a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}" class="flex gap-1 items-center">
            {{ column.header }}
            {% if column.is_ordered %}
                {% if "-" in column.order_by_alias %}
                    {% heroicon_micro "chevron-up" %}
                {% else %}
                    {% heroicon_micro "chevron-down" %}
                {% endif %}
            {% else %}
                {% heroicon_micro "chevron-up-down" class="sorting-indicator" %}
            {% endif %}
        </a>
    {% else %}
        {{ column.header }}
    {% endif %}
</th>

Upvotes: 0

Mike
Mike

Reputation: 67

I tried this answer, but prefer that the column header verbose name is closer to the text. I added code to the Table init():

for i in range(len(self.columns)):
        if is_blank(self.columns[i].column.verbose_name):
            my_label = self.columns[i].name.replace("_", " ").strip()
        else:
            my_label = self.columns[i].column.verbose_name.strip()

        arrow = '&#x21f5;' if self.columns[i].orderable else ""

        self.columns[i].column.verbose_name = mark_safe(f'{my_label} {arrow}')

To capture a different icon to indicate sorting, I used Tables.before_render(). By looking at the request, the GET field has a dict with a key of "sort" and a value that is the field_name. If it's a reverse sort, the field_name has a - prefix.

This seems a bit of a hack, but I can't find a better way. The upshot is the column header can reflect the sort.

Upvotes: 1

potable
potable

Reputation: 166

The answer provided in this question may solve your problem, though it it hard to know for sure without knowing what you have tried already with CSS.

The templates that come built-in with django-tables2 all render column attributes to the final HTML, so that a column that is defined as orderable=True will produce column header tags with an "orderable" class (e.g. <th class="orderable">). Furthermore, columns that have been selected to sort ascending or descending will have asc or desc class identifiers added on render.

So, you can set up a CSS rule that will render three different arrow images depending on the state of the orderable column:

table.table thead th.orderable {
    background: url(path_to_unsorted_indicator_image)
}

table.table thead th.asc.orderable {
    background: url(path_to_ascending_indicator_image)
}

table.table thead th.desc.orderable {
    background: url(path_to_descending_indicator_image)
}

Upvotes: 2

Related Questions