682 search results

Correcting the Form Action & Preventing Default

…the modal. To do that, we need to create a systematic way for our controller to communicate whether or not the form submit was successful. This new idea will serve us super well in the next tutorial when we Ajaxify more form submits with Turbo.

4:30
Testing Part 2: Functional Testing

…in two lines. This is lower-level, but waits for the aria-busy attribute to be added to the html element, which Turbo does when it's loading. Then it waits for it to go away: Try the test now: Then... pop open the screenshot…

12:36
Popover!

…once the user hovers. The popover library does have a way to do this. But as an extra, extra challenge, I want to do it with regular ol' Turbo frames. Because, Frames are really good at loading stuff via AJAX! Plus, we'll see a…

11:44
useTransition in a Neat, Reusable Module

…did. I love coding with Stimulus. In the next tutorial in the series - about Turbo - I hope to show prove that we can have an even more dynamic and speedy app while writing even less custom JavaScript. Let us know what cool stuff your building…

5:00
Fancier Toasts: Auto-close & Fading

…but that is exactly what we wanted! Our toast notification is polished and done. Tomorrow's adventure: diving into the third and final part of Turbo: Streams. These are the Swiss army knife of Turbo, and will let us solve a whole new set of…

7:34
Preloading

…rendering. For example, @hotwired/stimulus is critical, stimulus-bundle is critical because that's what loads our controllers, and @hotwired/turbo is also critical. When we refresh... nothing changes: we just have more modulepreload items in the HTML. If we run Lighthouse one more time…

9:14
Updating an Entity

… After voting, we end up right back on this page. And, thanks to Turbo, this is all happening via Ajax calls... which is a nice bonus. The only problem is that... it's so smooth that it's not super obvious that my vote was…

5:24
Querying the Database

…see a formatted version of it... though I need to refresh the page for this to work... because the Turbo JavaScript library we installed in the first tutorial doesn't always play nice with this profiler area. Anyways, we can also see a runnable version…

7:25
Mercure Hub's JWT Authorization

…in theory, we could write some JavaScript that listens to this topic and does something with that JSON. But remember: the turbo_stream_listen() function activates a Stimulus controller that is already listening to this topic. It's listening and waiting for a message whose…

6:58
3rd Party JavaScript Widgets

…boring one that says "New York weather". However, Turbo does see the script tag that's inside of the new body - the script tag that we have down at the bottom of base.html.twig - and it does re-execute these lines. But this time…

7:52
Fixing the Sweetalert Modal

…annoying problems with Turbo, which is cleaning up the snapshot, let's organize all of the new event code to make room for more turbo event listeners later. That will put us in a great position to discuss the last tricky thing with Turbo drive:…

7:14
137 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 122
beforeFetchResponse(event) {
const fetchResponse = event.detail.fetchResponse;
const redirectLocation = fetchResponse.response.headers.get('Turbo-Location');
if (!redirectLocation) {
return;
}
event.preventDefault();
Turbo.clearCache();
Turbo.visit(redirectLocation);
}
}
// ... lines 135 - 137
See Code Block in Script
134 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
constructor() {
// ... lines 6 - 17
document.addEventListener('turbo:before-fetch-request', (event) => {
this.beforeFetchRequest(event);
});
// ... lines 21 - 26
}
// ... lines 28 - 106
beforeFetchRequest(event) {
console.log(event);
}
// ... lines 111 - 130
}
// ... lines 132 - 134
See Code Block in Script
145 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 107
beforeFetchRequest(event) {
const frameId = event.detail.fetchOptions.headers['Turbo-Frame'];
if (!frameId) {
return;
}
const frame = document.querySelector(`#${frameId}`);
if (!frame || !frame.dataset.turboFormRedirect) {
return;
}
event.detail.fetchOptions.headers['Turbo-Frame-Redirect'] = 1;
}
// ... lines 122 - 145
See Code Block in Script
128 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 103
beforeFetchResponse(event) {
// ... lines 105 - 115
Turbo.visit(fetchResponse.location, {
action: 'restore'
});
}
// ... lines 121 - 124
}
// ... lines 126 - 128
See Code Block in Script
130 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 103
async beforeFetchResponse(event) {
// ... lines 105 - 113
event.preventDefault();
Turbo.clearCache();
const snapshot = Turbo.PageSnapshot.fromHTMLString(await fetchResponse.responseHTML);
Turbo.navigator.view.snapshotCache.put(fetchResponse.location, snapshot)
Turbo.visit(fetchResponse.location, {
action: 'restore'
});
}
// ... lines 123 - 126
}
// ... lines 128 - 130
See Code Block in Script
125 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 103
beforeFetchResponse(event) {
// ... lines 105 - 113
event.preventDefault();
Turbo.clearCache();
Turbo.visit(fetchResponse.location);
}
// ... lines 118 - 121
}
// ... lines 123 - 125
See Code Block in Script
118 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 103
beforeFetchResponse(event) {
if (!this.modal || !this.modal._isShown) {
return;
}
const fetchResponse = event.detail.fetchResponse;
if (fetchResponse.succeeded && fetchResponse.redirected) {
event.preventDefault();
Turbo.visit(fetchResponse.location);
}
}
}
// ... lines 116 - 118
See Code Block in Script
118 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
constructor() {
// ... lines 6 - 16
document.addEventListener('turbo:before-fetch-response', (event) => {
this.beforeFetchResponse(event);
});
// ... line 22
}
// ... lines 24 - 114
}
// ... lines 116 - 118
See Code Block in Script
122 lines | assets/turbo/turbo-helper.js
// ... lines 1 - 3
const TurboHelper = class {
// ... lines 5 - 115
getCurrentFrame() {
return document.querySelector('turbo-frame[busy]');
}
}
// ... lines 120 - 122
See Code Block in Script