The Problem:
- I have a component that performs navigation using a turbo frame. I would like to reflect the navigation changes in the window URL for better UX.
- According to the Turbo documentation, using
data-turbo-action='advance'
should change the history location and solve this issue. - However, the response document lacks the
<head>
tag. After the frame is loaded, all<meta>
tags disappear from the document when they should be retained.
The Question:
How can I preserve the original document’s <head>
tag when navigating in a turbo frame with data-turbo-action='advance'
?
Other Things I Tried to Reflect the Navigation in the Window URL:
- Performing navigation from the turbo frame only, and then using JS with
history.pushState({}, '', url)
. This did change the window URL, but when I tried to navigate to the previous page using the browser’s “back” button, the URL changed but the new frame was not fetched and loaded. - Navigating with
data-turbo-frame="_top"
instead ofdata-turbo-action='advance'
, but this requires a lot of changes in the JS controller.
The Code:
Pagination component that is wrapped with turbo-frame
tag:
// _pagination_component.html.slim
div data= { 'controller': 'pagination' }
= turbo_frame_tag "pagination_turbo_frame#{pagination_id}",
data: { action: 'turbo:frame-load->pagination#frameLoaded' }
= turbo_frame_tag :pagination_lazy_load_frame,
data: { 'pagination-target': 'container' }
= yield
= pagination_nav_component(pages_count, current_page, link_builder, distance_from_current_page:)
Inside the pagination component there is a nav component with links to navigate between pages:
// _pagination_nav_component.html.slim
nav id='pagination-nav'
ul
li
a href=link_builder.call(page) data-turbo-action='advance'
The response:
<html>
<head></head>
<body>
<div class="row h-100">
<div class="col h-100">
<div class="h-100 d-flex flex-column h-100">
<div class="row flex-grow-1">
<div class="col">
<div class="h-100" data-controller="pagination">
<div class="d-flex flex-row h-100">
<turbo-frame data-action="turbo:frame-load->pagination#frameLoaded" id="pagination_turbo_frame">
...
</turbo-frame>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
3