So I've been using Turbo and I love it. But I've been struggling with some basic things. For example I have a live chat that appears on every page and it has to load all the messages and their user relation (2 querys). I've added a "data-turbo-permanent" attribute (and an ID) to the live chat element and it works, but the server still has to render those elements.
My solution was to add a header to every Turbo request by searching for every "data-turbo-permanent" attribute on the page
Then in my blade templates I check if this header exists and return nothing if it does
// app.blade.php
<div id="live-chat" data-turbo-permanent>
// Check if header exists && has the "live-chat" id
@if(!(request()->hasHeader('Turbo-Permanent') && in_array('live-chat', json_decode(request()->header('Turbo-Permanent')))))
// My life chat html & logic
@endif
</div>
If I visit the page the first time or visit the page with Turbo and the element appears the first time, it gets rendered. And if I visit another page with Turbo and the element still exists, it doesn't get rendered and the response has an empty \
so Turbo knows not to delete the element, like this:
I bet this could be programmed in a much better way without having to check the request in the blade template and also the render method also needs the request checking logic which I didn't include here.
I'd also have a solution for persisting scroll positions with a custom "data-turbo-scroll" attribute
// app.js
Turbo['scrollPositionsToSave'] = []
document.addEventListener('turbo:before-visit', function () {
let elements = document.querySelectorAll('[data-turbo-scroll]')
elements.forEach(function(el) {
if (el.scrollTop) {
Turbo['scrollPositionsToSave'].push({ element: el, scrollPosition : el.scrollTop })
}
})
}, false)
document.addEventListener('turbo:load', function () {
Turbo['scrollPositionsToSave'].forEach(function(el) { el.element.scrollTo(0, el.scrollPosition) })
Turbo['scrollPositionsToSave'] = [];
}, false)
For the chat example, I think you could have a Turbo Frame inside the data-turbo-permanent element and load its contents after the page load (not using lazy loading turbo frames, manually triggering a form or something)
@tonysm It's not really what I'm looking for, the chat room has to be loaded from the start, without user input and without lazy loading. It also has to persist on every page. The "data-turbo-permanent" attribute is working like it should, but the server doesn't know that and still sends the data and does all the queries. With my method it would be possible to persist elements without rendering them multiple times and with little to no effort.
Hey, I don't think we should implement something custom in the package that is not part of the Turbo.js or Turbo Rails source (unless something like this already exists there?).
Consider bringing up this issue on the Hotwire Discuss forum, please. Others might have a solution for this that feels more like a 1st-party.
It sounds like it's more generic. I can totally see the same problem occurring in Rails. But there they use fragment caching, so this is maybe the only difference?
So I've been using Turbo and I love it. But I've been struggling with some basic things. For example I have a live chat that appears on every page and it has to load all the messages and their user relation (2 querys). I've added a "data-turbo-permanent" attribute (and an ID) to the live chat element and it works, but the server still has to render those elements.
My solution was to add a header to every Turbo request by searching for every "data-turbo-permanent" attribute on the page
Then in my blade templates I check if this header exists and return nothing if it does
If I visit the page the first time or visit the page with Turbo and the element appears the first time, it gets rendered. And if I visit another page with Turbo and the element still exists, it doesn't get rendered and the response has an empty \
I bet this could be programmed in a much better way without having to check the request in the blade template and also the render method also needs the request checking logic which I didn't include here.
I'd also have a solution for persisting scroll positions with a custom "data-turbo-scroll" attribute
For the chat example, I think you could have a Turbo Frame inside the
data-turbo-permanent
element and load its contents after the page load (not using lazy loading turbo frames, manually triggering a form or something)Subsequent requests would contain the turbo permanent element, but its contents would only load the first time the form enters the DOM.
(maybe event just a hidden link instead of the form?)
@tonysm I'm going to try that, thanks. To be honest I didn't understand any of those \ or \ elements.
@tonysm It's not really what I'm looking for, the chat room has to be loaded from the start, without user input and without lazy loading. It also has to persist on every page. The "data-turbo-permanent" attribute is working like it should, but the server doesn't know that and still sends the data and does all the queries. With my method it would be possible to persist elements without rendering them multiple times and with little to no effort.
Hey, I don't think we should implement something custom in the package that is not part of the Turbo.js or Turbo Rails source (unless something like this already exists there?).
Consider bringing up this issue on the Hotwire Discuss forum, please. Others might have a solution for this that feels more like a 1st-party.
I understand. This is just more or less laravel specific.
It sounds like it's more generic. I can totally see the same problem occurring in Rails. But there they use fragment caching, so this is maybe the only difference?