Avec l'évolution de l'écosystème de Symfony il devient de plus en plus accessible de créer des composants intéractifs sur son site internet sans passer par l'utilisation de Javascript. Dans cet article, nous allons voir comment intégrer un champ de recherche avec Symfony UX et les Composants Live.

Un exemple intégrant le sujet abordé est disponible sur mon projet Github Symfony Basics.

Ajouter Symfony UX au projet

Pour ajouter Symfony UX à notre projet, il suffit d'entrer la commande :

composer require symfony/ux-live-component

Créer le Composant Live

Pour obtenir un champ de recherche dynamique, il faut créer un Composant Live, celui-ci nous servira à chercher des objets de type Post et se nommera PostSearch.
Nous allons le créer dans src/Twig/Components avec le code qui suit :

<?php

namespace App\Twig\Components;

use App\Entity\Post;
use App\Repository\PostRepository;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;

#[AsLiveComponent('post_search', template: 'components/post_search.html.twig')]
class PostSearch
{
    use DefaultActionTrait;

    #[LiveProp(writable: true)]
    public ?string $query = null;

    public function __construct(private PostRepository $repository)
    {
    }

    public function getPosts(): array
    {
        return $this->repository->findBySearchQuery($this->query);
    }
}

On peut y voir que par défaut, il est définit le fait que nous avons un Composant Live, son nom, le template à utiliser, ses propriétés et une recherche en fonction de la requête que l'utilisateur va écrire dans le champ.

findBySearchQuery est une fonction personnalisée qui permet de retourner des résultats dynamiques selon le contenu d'une requête. Sa création est abordée dans un article dédié sur le site.

Intégration du composant dans le site

Maintenant que le composant est créé, il faut l'intégrer à notre site, pour cela, il faut d'abord créer son template dans un dossier templates/components/, il portera le nom post_search.html.twig :

<div{{ attributes }}>
    <label>
        <input type="text" data-model="query" placeholder="Recherche d'un article ici" class="mb-4" autofocus="autofocus"/>
    </label>

    {% if computed.posts|length > 0 %}
        <table class="table align-middle">
            <thead>
                <tr>
                    <th>Titre</th>
                    <th>Contenu</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                {% for post in computed.posts %}
                    <tr>
                        <td>{{ post.title }}</td>
                        <td>{{ post.content }}</td>
                        <td>
                            <a class="btn btn-outline-primary" href="{{ path('post_show', {'id': post.id}) }}">Afficher</a>
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% else %}
        <div class="mx-10 text-center">
            Aucun article trouvé pour votre recherche.
        </div>
    {% endif %}
</div>

Si le nombre d'articles trouvés est plus grand que 0, ils seront affichés, sinon, il y aura un message par défaut pour indiquer que rien n'a été trouvé dans la base de données.

Maintenant que tout est prêt, nous allons ajouter notre composant au site, pour cela, il faut ajouter query aux paramètres que l'on va passer à notre vue :

final class SiteController extends AbstractController
{
    ...

    #[Route('/posts', name: 'post_index', methods: ['GET'])]
    public function post_index(PostRepository $postRepository, Request $request): Response
    {
        return $this->render('site/post/index.html.twig', [
            'query' => (string) $request->query->get('q', ''),
        ]);
    }

    ...
}

Et pour finir, on ajoute le composant dans la vue concernée :

...

{{ component('post_search', { query : query }) }}

...

Nous avons maintenant un champ de recherche dynamique d'intégré sur notre site internet grâce à Symfony UX et les Composants Live.