Simple Page Navigation
Click the buttons below to load different pages without a full page reload.
Uses hx-swap-oob to update both content and navigation buttons in a single response.
Click the buttons below to load different pages without a full page reload.
Uses hx-swap-oob to update both content and navigation buttons in a single response.
This demo showcases the htmx-bundle for Symfony.
<?php
declare(strict_types=1);
namespace App\Controller;
use Mdxpl\HtmxBundle\Request\HtmxRequest;
use Mdxpl\HtmxBundle\Response\HtmxResponse;
use Mdxpl\HtmxBundle\Response\HtmxResponseBuilder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
#[Route('/simple-page/{slug}', name: 'app_simple_page')]
final class SimplePageController extends AbstractController
{
private const PAGES = [
'home' => ['name' => 'Home', 'description' => 'Welcome to the htmx-bundle demo! Navigate using the menu above.'],
'about' => ['name' => 'About', 'description' => 'This demo showcases the htmx-bundle for Symfony.'],
'contact' => ['name' => 'Contact', 'description' => 'Get in touch with us for more information.'],
];
public function __invoke(HtmxRequest $htmx, string $slug = 'home'): HtmxResponse
{
$page = self::PAGES[$slug] ?? throw new NotFoundHttpException('Page not found');
$viewData = [
'menu' => self::PAGES,
'page' => $page,
'currentSlug' => $slug,
];
$builder = HtmxResponseBuilder::create($htmx->isHtmx);
if ($htmx->isHtmx) {
return $builder
->success()
->viewBlock('simple_page.html.twig', 'pageContent', $viewData)
->viewBlock('simple_page.html.twig', 'pageNav', $viewData)
->build();
}
return $builder
->success()
->view('simple_page.html.twig', $viewData)
->build();
}
}
{% block pageNav %}
<nav id="page-nav" hx-swap-oob="true">
<ul>
{% for slug, item in menu %}
<li>
<a href="{{ path('app_simple_page', {'slug': slug}) }}"
{{ currentSlug == slug ? 'aria-current="page"' : '' }}
hx-get="{{ path('app_simple_page', {'slug': slug}) }}"
hx-push-url="true"
hx-target="#pageContent"
hx-swap="innerHTML transition:true"
hx-indicator="#loader">
{{ item.name }}
</a>
</li>
{% endfor %}
</ul>
</nav>
{% endblock %}
{% block pageContent %}
<title>{{ page.name }} - Simple Page Demo</title>
<article>
<header><strong>{{ page.name }}</strong></header>
<p>{{ page.description }}</p>
</article>
{% endblock %}