hx-push-url doesn’t work properly on device back button click
See original GitHub issueI am trying to integrate Htmx with django and achieve single page application behaviour. I am rewritting Djangoproject.com poll app with htmx. When I click on detail page link, content loads, htmx push a new url in address bar. When I press back button, it took me to index page perfectly for the first time, after that if I again go to detail page and click back button, url shows of the index, but index content doesn’t load, content remains same as detail page. Here is my code -
views.py
def index(request):
latest_question_list = Question.objects.filter(pub_date__lte=timezone.now()).order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
if request.headers.get("Hx-Request") is not None:
return render(request, 'main/index/index.html', context)
else:
return render(request, 'main/index/index-full.html', context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
print(request.headers.get("Hx-Request"))
if request.headers.get("Hx-Request") is not None:
return render(request, 'main/detail/detail.html', {'question': question})
else:
return render(request, 'main/detail/detail-full.html', {'question': question})
index.html
<div id="index" class="">
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><div class="has-text-link" hx-get="{% url 'main:detail' question.id %}" hx-push-url="true" hx-target="#index" hx-swap="outerHTML">{{ question.question_text }}</div></li>
{% endfor %}
</ul>
{% else %}
<p>
No polls are available.
</p>
{% endif %}
</div>
index-full.html
{% extends 'base.html' %}
{% block content %}
{% include 'main/index/index.html' %}
{% endblock content %}
detail.html
<div id="detail" class="">
<form action="{% url 'main:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ question.question_text }}</h1></legend>
{% if error_message %}<p>
<strong>{{ error_message }}</strong>
</p>
{% endif %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>
</div>
detail-full.html
{% extends 'base.html' %}
{% block content %}
{% include 'main/detail/detail.html %}
{% endblock content %}
I found no error in browser console, no error in terminal
Now, I know I can put a back button in detail page that can took me to index page. But user won’t use that, they will just use the back button on their device. Note- I am on Android and talking about the back button in mobile phones
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:24 (13 by maintainers)
Top Related StackOverflow Question
Wow @gone nice catch!! Just tested importing of
htmx.jsfrom<head>instead of<body>, the issue is… gone 😉 . Let’s see what the best fix is 👍Just did a debug of this, and in the bottle example the error is coming from reloading htmx multiple times. It looks like on the reload of the cached version the currentPathForHistory is reset when it loads.
You can fix the bottle example by EITHER setting currentPathForHistory in the htmx source to window.currentPathForHistory (making it a global) or by moving the htmx load to the head like so:
Another example of multiple initialization is the loading styling being applied multiple times. @David-Guillot I’m pretty sure this is the same case for the bug you’re seeing because after clicking through a couple of your hubs I can see in the header multiple instances of:
<style> .htmx-indicator{opacity:0;transition: opacity 200ms ease-in;} .htmx-request .htmx-indicator{opacity:1} .htmx-request.htmx-indicator{opacity:1} </style>which makes me think you are also reloading htmx multiple times.
I think the workaround right now is moving htmx to your header - @1cg should the long term fix be having htmx notice it’s already been loaded and do nothing?