OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

DataTable table ordering fails when used in HTMX responsive table

  • Thread starter Thread starter Bonny Clarke
  • Start date Start date
B

Bonny Clarke

Guest
I have played around with a few ways to create responsive tables and I like the htmx approach. The issue I run into is I loose some of the DataTables functions I have relied upon, mainly the ability for the user to sort by clicking on the header.

Views.py:

Code:
    class HomePageView(TemplateView):
        template_name = 'wwdb/home_tabletest.html'
    
    class WinchOperatorForm(forms.ModelForm):
        class Meta:
            model = WinchOperator
            exclude = []
    
    def get_winchoperator_list(request):
        context = {}
        context['winchoperator'] = WinchOperator.objects.all()
        return render(request, 'wwdb/winchoperator_list.html', context)
    
    def add_winchoperator(request):
        context = {'form': WinchOperatorForm()}
        return render(request, 'wwdb/add_winchoperator.html', context)
    
    def add_winchoperator_submit(request):
        context = {}
        form = WinchOperatorForm(request.POST)
        context['form'] = form
        if form.is_valid():
            context['winchoperator'] = form.save()
        else:
            return render(request, 'wwdb/add_winchoperator.html', context)
        return render(request, 'wwdb/winchoperator_row.html', context)
    
    def add_winchoperator_cancel(request):
        return HttpResponse()
    
    def delete_winchoperator(request, winchoperator_pk):
        winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
        winchoperator.delete()
        return HttpResponse()
    
    def edit_winchoperator(request, winchoperator_pk):
        winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
        context = {}
        context['winchoperator'] = winchoperator
        context['form'] = WinchOperatorForm(initial={
            'firstname':winchoperator.firstname,
            'lastname': winchoperator.lastname,
            'status': winchoperator.status,
            'username': winchoperator.username,
        })
        return render(request, 'wwdb/edit_winchoperator.html', context)
    
    def edit_winchoperator_submit(request, winchoperator_pk):
        context = {}
        winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
        context['winchoperator'] = winchoperator
        if request.method == 'POST':
            form = WinchOperatorForm(request.POST, instance=winchoperator)
            if form.is_valid():
                form.save()
            else:
                return render(request, 'wwdb/edit_winchoperator.html', context)
        return render(request, 'wwdb/winchoperator_row.html', context)

I can post more templates if requested, but the template defining the tables are:

Code:
    <div>
        <table class="table display">
            <thead>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Status</th>
            <th>Username</th>
            <th>test</th>
            <th>test</th>
            </thead>
            <tbody>
                {% for winchoperator in winchoperator %}
                <tr>
                    <td>{{ winchoperator.firstname }}</td>
                    <td>{{ winchoperator.lastname }}</td>
                    <td>{{ winchoperator.status }}</td>
                    <td>{{ winchoperator.username }}</td>
                    <td>
                        <button class='btn'
                                hx-get="{% url 'edit_winchoperator' winchoperator.pk %}"
                                hx-target="closest tr"
                                hx-swap="outerHTML">
                            <svg class="bi bi-pencil" width="32" height="32">
                                <use xlink:href="#pencil">
                            </svg>
                        </button>
                    </td>
                    <td>
                        <button class='btn'
                                hx-confirm='Are you sure?'
                                hx-target="closest tr"
                                hx-swap="outerHTML swap:1s"
                                hx-delete="{% url 'delete_winchoperator' winchoperator.pk %}">
                            <svg class="bi bi-trash3" width="32" height="32">
                                <use xlink:href="#trash3">
                            </svg>
                        </button>
                    </td>
                </tr>            
                {% endfor %}
            </tbody>
        </table>
    </div>

Code:
    <!DOCTYPE html>
    <body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
        <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
            <symbol id="checkmark" viewBox="0 0 16 16">
                <path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425a.247.247 0 0 1 .02-.022Z" />
            </symbol>
            <symbol id="cancel" viewBox="0 0 16 16">
                <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z" />
            </symbol>
            <symbol id="pencil" viewBox="0 0 16 16">
                <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" />
            </symbol>
            <symbol id="trash3" viewBox="0 0 16 16">
                <path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.506a.58.58 0 0 0-.01 0H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1h-.995a.59.59 0 0 0-.01 0H11Zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5h9.916Zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47ZM8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5Z" />
            </symbol>
            <symbol id="plus" viewBox="0 0 16 16">
                <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
            </symbol>
        </svg>
        <button class='btn'
                hx-get="{% url 'add_winchoperator' %}"
                hx-target="next tbody" 
                hx-swap="afterbegin">
            <svg class="bi bi-plus" width="32" height="32">
                <use xlink:href="#plus">
            </svg>
        </button>
        <div id="query_result"
             hx-target="this"
             hx-swap="innerHTML"
             hx-get="{% url 'get_winchoperator_list' %}"
             hx-trigger="load delay:1s">
        </div>
    </body>

The datatable class I am referring to is in my base.py file, which is loaded in the template.

Code:
    <script type="text/javascript">
        $(document).ready(function () {
            $('table.display').DataTable({
                autoWidth: false,
                scrollX: true
            });
            // Listen for Bootstrap tab activation event
            $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
                // Get the DataTable instance of the active tab
                var activeTable = $($(e.target).attr('href')).find('table').DataTable();
                // Adjust columns when the tab becomes active
                activeTable.columns.adjust().draw();
            });
        });
    </script>

I used the following tutorial to get where I am now. Loved the tutorial but want to find a way to integrate it into the tables I already have in place.

Code:
https://medium.com/@duytran2310/django-crud-inside-a-table-with-htmx-part-1-53dd8417c36a
<p>I have played around with a few ways to create responsive tables and I like the htmx approach. The issue I run into is I loose some of the DataTables functions I have relied upon, mainly the ability for the user to sort by clicking on the header.</p>
<p>Views.py:</p>
<pre><code> class HomePageView(TemplateView):
template_name = 'wwdb/home_tabletest.html'

class WinchOperatorForm(forms.ModelForm):
class Meta:
model = WinchOperator
exclude = []

def get_winchoperator_list(request):
context = {}
context['winchoperator'] = WinchOperator.objects.all()
return render(request, 'wwdb/winchoperator_list.html', context)

def add_winchoperator(request):
context = {'form': WinchOperatorForm()}
return render(request, 'wwdb/add_winchoperator.html', context)

def add_winchoperator_submit(request):
context = {}
form = WinchOperatorForm(request.POST)
context['form'] = form
if form.is_valid():
context['winchoperator'] = form.save()
else:
return render(request, 'wwdb/add_winchoperator.html', context)
return render(request, 'wwdb/winchoperator_row.html', context)

def add_winchoperator_cancel(request):
return HttpResponse()

def delete_winchoperator(request, winchoperator_pk):
winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
winchoperator.delete()
return HttpResponse()

def edit_winchoperator(request, winchoperator_pk):
winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
context = {}
context['winchoperator'] = winchoperator
context['form'] = WinchOperatorForm(initial={
'firstname':winchoperator.firstname,
'lastname': winchoperator.lastname,
'status': winchoperator.status,
'username': winchoperator.username,
})
return render(request, 'wwdb/edit_winchoperator.html', context)

def edit_winchoperator_submit(request, winchoperator_pk):
context = {}
winchoperator = WinchOperator.objects.get(pk=winchoperator_pk)
context['winchoperator'] = winchoperator
if request.method == 'POST':
form = WinchOperatorForm(request.POST, instance=winchoperator)
if form.is_valid():
form.save()
else:
return render(request, 'wwdb/edit_winchoperator.html', context)
return render(request, 'wwdb/winchoperator_row.html', context)

</code></pre>
<p>I can post more templates if requested, but the template defining the tables are:</p>
<pre><code>
<div>
<table class="table display">
<thead>
<th>First Name</th>
<th>Last Name</th>
<th>Status</th>
<th>Username</th>
<th>test</th>
<th>test</th>
</thead>
<tbody>
{% for winchoperator in winchoperator %}
<tr>
<td>{{ winchoperator.firstname }}</td>
<td>{{ winchoperator.lastname }}</td>
<td>{{ winchoperator.status }}</td>
<td>{{ winchoperator.username }}</td>
<td>
<button class='btn'
hx-get="{% url 'edit_winchoperator' winchoperator.pk %}"
hx-target="closest tr"
hx-swap="outerHTML">
<svg class="bi bi-pencil" width="32" height="32">
<use xlink:href="#pencil">
</svg>
</button>
</td>
<td>
<button class='btn'
hx-confirm='Are you sure?'
hx-target="closest tr"
hx-swap="outerHTML swap:1s"
hx-delete="{% url 'delete_winchoperator' winchoperator.pk %}">
<svg class="bi bi-trash3" width="32" height="32">
<use xlink:href="#trash3">
</svg>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

</code></pre>
<pre><code> <!DOCTYPE html>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="checkmark" viewBox="0 0 16 16">
<path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425a.247.247 0 0 1 .02-.022Z" />
</symbol>
<symbol id="cancel" viewBox="0 0 16 16">
<path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z" />
</symbol>
<symbol id="pencil" viewBox="0 0 16 16">
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" />
</symbol>
<symbol id="trash3" viewBox="0 0 16 16">
<path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.506a.58.58 0 0 0-.01 0H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1h-.995a.59.59 0 0 0-.01 0H11Zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5h9.916Zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47ZM8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5Z" />
</symbol>
<symbol id="plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
</symbol>
</svg>
<button class='btn'
hx-get="{% url 'add_winchoperator' %}"
hx-target="next tbody"
hx-swap="afterbegin">
<svg class="bi bi-plus" width="32" height="32">
<use xlink:href="#plus">
</svg>
</button>
<div id="query_result"
hx-target="this"
hx-swap="innerHTML"
hx-get="{% url 'get_winchoperator_list' %}"
hx-trigger="load delay:1s">
</div>
</body>

</code></pre>
<p>The datatable class I am referring to is in my base.py file, which is loaded in the template.</p>
<pre><code> <script type="text/javascript">
$(document).ready(function () {
$('table.display').DataTable({
autoWidth: false,
scrollX: true
});
// Listen for Bootstrap tab activation event
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
// Get the DataTable instance of the active tab
var activeTable = $($(e.target).attr('href')).find('table').DataTable();
// Adjust columns when the tab becomes active
activeTable.columns.adjust().draw();
});
});
</script>
</code></pre>
<p>I used the following tutorial to get where I am now. Loved the tutorial but want to find a way to integrate it into the tables I already have in place.</p>
<pre><code>https://medium.com/@duytran2310/django-crud-inside-a-table-with-htmx-part-1-53dd8417c36a
</code></pre>
 

Latest posts

P
Replies
0
Views
1
Paras Chouhan
P
Top