Bonus More on Flowbite
... little JavaScript so that when we click, this opens and closes.
We're not using this at SymfonyCasts... and it doesn't play well with Turbo. At
least not out of the box. We prefer to create tiny Stimulus controllers to ...
Live Components
Happy Day 27 of Last Stack! We've accomplished a lot during the first 26 days with
just three letters of LAST Stack: Asset Mapper, Stimulus, and Turbo. Today
we crack the code on the L of LAST Stack: Live components ...
Modal Twig Component
... <twig:Modal>. Easy!
However, look closer at Modal.html.twig: there are some things that shouldn't
be here. For example, the <turbo-frame>! Not every modal needs a frame.
A lot of times, we'll render a modal with simple ...
As a note, Turbo 8 (added in UX v2.15.0) includes "InstantClick" (https://turbo.hotwired.dev/handbook/drive#instantclick) which causes a pre-load like event (and additional XHR calls) on hover.
InstantClick also ...
Thanks Ryan! Your solution is working well but, you're right :
> when you redirect from LiveAction, LiveComponents sees that and checks to see if Turbo is installed. If it is, it does a Turbo.visit() instead of a real ...
... Hey again!
> but is this topic of the turbo and the hotwire very new
Fortunately, no. Both Turbo and Stimulus are about 10 (yes 10!) years old. Though the most recent version of both was released 2-3 years ago ...
Hello,
I am using UX Turbo, I watched this doc : https://github.com/symfony/ux-turbo/#sending-async-changes-using-mercure-a-chat
I wanted to know if it is possible to push data to selected users through a query, but ...
... the template for a page, you embed a controller (`render(controller())` correct?) that renders a contact form.
Question: (ignoring Turbo for a moment - just pretend you're on a non-Turbo site), where does that contact ...
... closer at the JS code... though your code looks pretty similar to the core Mercure + Turbo code (it's not exactly the same use-case, but the EventSource stuff is the same - https://github.com/symfony/ux/blob/main/src/Turbo/Bridge/Mercure/Resources/assets/src/turbo_stream_controller.js )
Sorry I can't be more help!
Cheers!
Hey Nick F.!
You're right! That was some sloppiness by me. I added data-turbo-cache="false" to the "flash-container" element. And so, it's removed when cleaning up the page. That's... not really want I want to do ...
Hey Ruslan!
That's a pretty fair question :). My choice would be a multi-page app with Twig, but with Turbo and Stimulus immediately so that you can get the "single page app" feel. However, if what you're building is ...
|
// ... lines 1 - 3
|
|
<turbo-frame id="product-info" target="_top" class="row pt-3 product-show"> |
|
<div class="col-4"> |
|
<img |
|
alt="{{ product.name }}" |
|
src="{{ asset('/uploads/products/'~product.imageFilename) }}" |
|
class="d-block" |
|
> |
|
<div class="p-2"> |
|
<small>brought to you by </small> |
|
<small class="d-inline">{{ product.brand }}</small> |
|
</div> |
|
</div> |
|
<div class="col-8 px-3"> |
|
<h1> |
|
{{ product.name }} |
|
{% if is_granted('ROLE_ADMIN') %} |
|
<a |
|
href="{{ path('product_admin_edit', { |
|
id: product.id |
|
}) }}" |
|
class="btn btn-sm btn-secondary" |
|
>Edit</a> |
|
{% endif %} |
|
</h1> |
|
<div> |
|
{{ product.description }} |
|
</div> |
|
<div class="p-3 mt-4 d-flex justify-content-between flex-wrap flex-lg-nowrap"> |
|
<div> |
|
<strong>{{ product.priceString|format_currency('USD') }}</strong> |
|
<br> |
|
<strong>{{ product.reviews|length }}</strong> Reviews |
|
<br/> |
|
<strong>{{ product.averageStars }}/5</strong><i class="fas fa-star ms-2"></i> |
|
</div> |
|
<div> |
|
{{ include('product/_cart_add_controls.html.twig') }} |
|
</div> |
|
</div> |
|
</div> |
|
</turbo-frame> |
|
// ... lines 45 - 52
|
See Code Block in Script
|
// ... lines 1 - 2
|
|
{% block productBody %} |
|
<div class="row pt-3 product-show"> |
|
<turbo-frame id="product-info" target="_top"> |
|
<div class="col-4"> |
|
<img |
|
alt="{{ product.name }}" |
|
src="{{ asset('/uploads/products/'~product.imageFilename) }}" |
|
class="d-block" |
|
> |
|
<div class="p-2"> |
|
<small>brought to you by </small> |
|
<small class="d-inline">{{ product.brand }}</small> |
|
</div> |
|
</div> |
|
<div class="col-8 px-3"> |
|
<h1> |
|
{{ product.name }} |
|
{% if is_granted('ROLE_ADMIN') %} |
|
<a |
|
href="{{ path('product_admin_edit', { |
|
id: product.id |
|
}) }}" |
|
class="btn btn-sm btn-secondary" |
|
>Edit</a> |
|
{% endif %} |
|
</h1> |
|
<div> |
|
{{ product.description }} |
|
</div> |
|
<div class="p-3 mt-4 d-flex justify-content-between flex-wrap flex-lg-nowrap"> |
|
<div> |
|
<strong>{{ product.priceString|format_currency('USD') }}</strong> |
|
<br> |
|
<strong>{{ product.reviews|length }}</strong> Reviews |
|
<br/> |
|
<strong>{{ product.averageStars }}/5</strong><i class="fas fa-star ms-2"></i> |
|
</div> |
|
<div> |
|
{{ include('product/_cart_add_controls.html.twig') }} |
|
</div> |
|
</div> |
|
</div> |
|
</turbo-frame> |
|
</div> |
|
// ... lines 47 - 54
|
See Code Block in Script
|
<!DOCTYPE html> |
|
<html> |
|
// ... lines 3 - 15
|
|
<body class="bg-black text-white font-mono"> |
|
// ... lines 17 - 54
|
|
<twig:Modal> |
|
<turbo-frame |
|
// ... lines 57 - 62
|
|
</turbo-frame> |
|
<twig:block name="loading_template"> |
|
<div class="bg-space-pattern bg-cover rounded-lg p-8"> |
|
<div class="space-y-2"> |
|
<div class="h-4 bg-gray-700 rounded w-3/4 animate-pulse"></div> |
|
<div class="h-4 bg-gray-700 rounded animate-pulse"></div> |
|
<div class="h-4 bg-gray-700 rounded animate-pulse"></div> |
|
<div class="h-4"></div> |
|
<div class="h-4 bg-gray-700 rounded animate-pulse"></div> |
|
<div class="h-4 bg-gray-700 rounded w-1/2 animate-pulse"></div> |
|
<div class="h-4 bg-gray-700 rounded w-3/4 animate-pulse"></div> |
|
<div class="h-4"></div> |
|
<div class="h-4 bg-gray-700 rounded w-1/2 animate-pulse"></div> |
|
</div> |
|
</div> |
|
</twig:block> |
|
</twig:Modal> |
|
</body> |
|
</html> |
See Code Block in Script
|
// ... lines 1 - 4
|
|
{% block body %} |
|
<div class="flex"> |
|
// ... lines 7 - 13
|
|
<section class="flex-1 ml-10"> |
|
// ... lines 15 - 29
|
|
<div class="bg-gray-800 p-4 rounded"> |
|
<table class="w-full text-white"> |
|
// ... lines 32 - 38
|
|
<tbody> |
|
{% for voyage in voyages %} |
|
<tr class="border-b border-gray-700 {% if loop.index is odd %} bg-gray-800 {% else %} bg-gray-700 {% endif %}"> |
|
// ... line 42
|
|
<td class="px-2 whitespace-nowrap"> |
|
<div |
|
data-controller="popover" |
|
data-action="mouseenter->popover#show mouseleave->popover#hide" |
|
class="relative" |
|
> |
|
// ... lines 49 - 54
|
|
<template data-popover-target="content"> |
|
<div |
|
data-popover-target="card" |
|
class="max-w-sm rounded shadow-lg bg-gray-900 absolute left-0 bottom-10" |
|
> |
|
<turbo-frame id="planet-card-{{ voyage.planet.id }}" src="{{ path('app_planet_show_card', { |
|
'id': voyage.planet.id, |
|
}) }}"></turbo-frame> |
|
</div> |
|
</template> |
|
</div> |
|
</td> |
|
// ... line 67
|
|
</tr> |
|
{% endfor %} |
|
</tbody> |
|
</table> |
|
</div> |
|
// ... lines 73 - 76
|
|
</section> |
|
</div> |
|
{% endblock %} |
See Code Block in Script
|
// ... lines 1 - 4
|
|
{% block body %} |
|
<div class="flex"> |
|
// ... lines 7 - 13
|
|
<section class="flex-1 ml-10"> |
|
// ... lines 15 - 29
|
|
<div class="bg-gray-800 p-4 rounded"> |
|
<table class="w-full text-white"> |
|
// ... lines 32 - 38
|
|
<tbody> |
|
{% for voyage in voyages %} |
|
<tr class="border-b border-gray-700 {% if loop.index is odd %} bg-gray-800 {% else %} bg-gray-700 {% endif %}"> |
|
// ... line 42
|
|
<td class="px-2 whitespace-nowrap"> |
|
<div |
|
data-controller="popover" |
|
data-action="mouseenter->popover#show mouseleave->popover#hide" |
|
class="relative" |
|
> |
|
// ... lines 49 - 54
|
|
<template data-popover-target="content"> |
|
<div |
|
data-popover-target="card" |
|
class="max-w-sm rounded shadow-lg bg-gray-900 absolute left-0 bottom-10" |
|
> |
|
<turbo-frame id="planet-card-{{ voyage.planet.id }}" src="{{ path('app_planet_show_card', { |
|
'id': voyage.planet.id, |
|
}) }}"></turbo-frame> |
|
</div> |
|
</template> |
|
</div> |
|
</td> |
|
// ... line 67
|
|
</tr> |
|
{% endfor %} |
|
</tbody> |
|
</table> |
|
</div> |
|
// ... lines 73 - 76
|
|
</section> |
|
</div> |
|
{% endblock %} |
See Code Block in Script
Lazy Stimulus Controllers
... downloaded. I love this feature.
This can also be done for third-party packages. If you look in
assets/controllers.json... Turbo isn't a very good example of this, but if we
said "fetch": "lazy" on any of these, they would ...
Blog
Live Stream 7 Let's build some Twig UI Components
... recording setup and re-recording bad audio 11:15
New proposed Twig components attribute syntax 13:40
UI Recipes: What is all this? 18:45
The WIP recipes site with starting recipes 29:15
Building a Dropdown component 41:15
Why teleporting is probably not needed & using Turbo Streams 51:00
So, why would one choose Vue or React or stimulus? What do you think the choice is based on?
Is [this the most recent guide](https://symfonycasts.com/screencast/last-stack) on the stimulus/turbo topic? Or are there more recent ones?
thanks ...
If I recall correctly, the modal closes automatically when its content is cleared out, so you only need to empty the modal's content. Your response should return a turbo stream with the same modal's id but with no HTML ...
590
Turbo
Filter Results