Alternate Layout pour un Custom Field de type SubForm (le nouveau type de Joomla 4)

Réduire
X
 
  • Filtrer
  • Heure
  • Afficher
Tout effacer
nouveaux messages

  • Alternate Layout pour un Custom Field de type SubForm (le nouveau type de Joomla 4)


    Bonjour tout le monde,

    Pour la prochaine édition du Joomla Community Magazine, je voulais montrer comment utiliser le nouveau Custom Field de type SubForm introduit dans Joomla4.

    J'ai créé trois champs :
    1. Titre
    2. Durée
    3. Media

    et je crée l'Alternate Layout suivant qui transforme ce champ répétable... en carousel.

    Rien à installer et aucun script à ajouter : c'est 100% natif

    Vos suggestions d'améliorations sont les bienvenues, certes pour le toilettage, mais aussi et surtout pour pouvoir ajouter l'ID de l'article à l'identifiant de la <div> du carrousel (afin de pouvoir les faire fonctionner aussi en vue blog).

    Code HTML:
    <?php
    
    /* this is an Alternate Layout of /components/com_fields/layouts/field/render.php */
    /* for an explanation of Alternate Layout for Custom Fields, see
    https://magazine.joomla.org/all-issues/may-2021/explore-the-core-play-with-custom-fields-to-enrich-your-content-or-your-design */
    
    defined('_JEXEC') or die;
    
    
    
    if (!array_key_exists('field', $displayData))
    {
    return;
    }
    
    $field = $displayData['field'];
    /*$label = Text::_($field->label);*/ // commented bc not needed for Alternated Layout
    $value = $field->value;
    $rawvalue = $field->rawvalue; // added for Alternated Layout
    $showLabel = $field->params->get('showlabel');
    $labelClass = $field->params->get('label_render_class');
    $renderClass = $field->params->get('render_class');
    
    if ($value == '')
    {
    return;
    }
    
    ?>
    <?php
    $app = JFactory::getApplication();
    $view = $app->input->getCMD('view', ''); // "view" would output "article" or "category" for example
    // $id = $app->input->getCMD('id', ''); // "id" gives the id of the category if blog view, the id of the article if article view
    if ($view != "article") { return; } // if the view is not an article view (but a blog view or whatever) then nothing will be displayed
    ?>
    
    <?php // TO DO - customize "carouselWithCustomFields" with the ID of the article so that it would also work on a blog view where we need a unique id for each carousel ?>
    
    <?php // https://docs.joomla.org/J4.x:Using_Bootstrap_Components_in_Joomla_4
    \Joomla\CMS\HTML\HTMLHelper::_('bootstrap.carousel ', '#carouselWithCustomFields', ['interval' => 3000, 'pause' => 'false']); // selector is necessary for the potentials Options to work ?>
    
    <?php $items = json_decode($rawvalue, true); ?>
    
    <div id="carouselWithCustomFields" class="carousel slide carousel-fade" data-bs-ride="carousel">
    <div class="carousel-indicators">
    <?php $first=true; $i=0; ?>
    <?php foreach($items as $item): ?>
    <button <?php if ($first) {echo "class="active""; $first=false;} ?> type="button" data-bs-target="#carouselWithCustomFields" data-bs-slide-to="<?php echo $i; ?>" aria-current="true" aria-label="<?php echo $item['field1']; ?>"></button>
    <?php $i=$i+1; ?>
    <?php endforeach; ?>
    </div>
    <div class="carousel-inner">
    <?php $first=true; ?>
    <?php foreach($items as $item): ?>
    <div class="carousel-item <?php if ($first) {echo "active"; $first=false;} ?>" data-bs-interval="<?php echo 1000*$item['field2']; ?>">
    <img class="d-block w-100" src="<?php echo $item['field3']['imagefile']; ?>" />
    <div class="carousel-caption d-none d-md-block">
    <h5><?php echo $item['field1']; ?></h5>
    </div>
    </div>
    <?php endforeach; ?>
    </div>
    <button class="carousel-control-prev" type="button" data-bs-target="#carouselWithCustomFields" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Previous</span>
    </button>
    <button class="carousel-control-next" type="button" data-bs-target="#carouselWithCustomFields" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Next</span>
    </button>
    </div>
    
    <?php
    $myCarouselCss = <<<MYCSS
    /* example of CSS for bootstrap.carousel - adding a background to the carousel-caption - see https://ui.glass/generator/ for glassmorphism CSS */
    .carousel-caption {
    bottom: 40%; /* otherwise with our background too close from Indicators with the default 1.25rem */
    left: 25%; /* to make it narrower than with the default 15% */
    right: 25%; /* to make it narrower than with the default 15% */
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    background-color: rgba(0,0,0,0.5);
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.125);
    }
    /* by default the custom fields appear in a Unordered List. To make the carousel start on the left and hide the bullet point we use a negative margin */
    li.field-entry.mycarousel {
    margin-left: -2rem;
    }
    MYCSS;
    
    use Joomla\CMS\Factory;
    $doc = Factory::getDocument();
    $doc->addStyleDeclaration($myCarouselCss);
    ?>
    
    
    
    <?php // Everything after the "return" will be ignored ?>
    <?php return ?>
    
    
    <?php // this would render the value of the Custom Field ?>
    <span class="field-value <?php echo $renderClass; ?>"><?php echo $value; ?></span>
    
    
    <?php // this would render the rawvalue of the Custom Field ?>
    <span class="field-value <?php echo $renderClass; ?>"><?php echo $rawvalue; ?></span>
    
    
    <?php // this would render the json as numbered list ?>
    <?php $items = json_decode($rawvalue, true); ?>
    <?php foreach($items as $item): ?>
    <ul>
    <li><?php echo $item['field1']; ?></li>
    <li><?php echo $item['field2']; ?></li>
    <li><?php echo $item['field3']['imagefile']; ?></li>
    </ul>
    <?php endforeach; ?>
    Présentations : slides.woluweb.be | Coordonnées complètes : www.woluweb.be

    Un message d’erreur sur votre site Joomla... ayez le reflexe de consulter la base de connaissance : https://kb.joomla.fr

    Ce forum, vous l'aimez ? Il vous a sauvé la vie ? Vous y apprenez régulièrement ? Alors adhérer à l'AFUJ, l'Association Francophone des Utilisateurs de Joomla : https://www.joomla.fr/association/adherer

  • #2
    Hello Marc

    Une remarque sur le code : il y a un mix à de multiples endroits entre PHP et HTML et, tu connais l'adage concernant les goûts et les couleurs ...

    Perso, je n'aime pas du tout et je présume que cela a un impact négatif sur les performances du moteur PHP qui doit jongler entre les différents tags.

    Voici, pour la partie finale de ton code, ce que je ferais perso:

    Code PHP:
    <?php // this would render the json as numbered list

    $items json_decode($rawvaluetrue);

    foreach(
    $items as $item)
    {
       echo
          
    '<ul>'.
             
    '<li>' $item['field1'] . '</li>' .
             
    '<li>' $item['field2'] . '</li>' .
             
    '<li>' $item['field3']['imagefile'] . '</li>' .
          
    '</ul>';
    }
    (non testé)
    manu93fr et woluweb aiment ceci.
    Christophe (cavo789)
    Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be
    Logiciel gratuit de scan antivirus : https://github.com/cavo789/aesecure_quickscan (plus de 45.000 virus détectés, 700.000 fichiers sur liste blanche)​

    Commentaire


    • #3
      +1 avec cavo789 une boucle sera plus adaptée

      au passage, j'ai pas encore jeté un oeil sur le nouveau Custom Field de type SubForm, tu veux constuire quoi au final?
      Expert en conception et réalisation de sites Internet 100% Joomla
      www.toonetcreation.com

      Commentaire


      • #4
        Le but est de faire une démo du Custom Field de Type SubForm.

        J'ai choisi de construire un carousel pcq
        - ça demande plusieurs champs de types différents (titre, durée, image)
        - on peut avoir tantôt deux slides, tantôt 10
        - ça permet de faire autre chose que d'afficher le contenu en "bullet points" et c'est déjà un peu plus avancé qu'un simple affichage statique
        - ça permet de montrer aussi comment déclencher le javascript de bootstrap, mais juste la partie dont on a besoin (carousel ici)

        Illustration :
        Joomla 4: preparing the next article about Custom Fields for the Joomla Community Magazine :) I will show how to use the new Type of Custom Field called "SubForm" to create a carousel within an...
        Présentations : slides.woluweb.be | Coordonnées complètes : www.woluweb.be

        Un message d’erreur sur votre site Joomla... ayez le reflexe de consulter la base de connaissance : https://kb.joomla.fr

        Ce forum, vous l'aimez ? Il vous a sauvé la vie ? Vous y apprenez régulièrement ? Alors adhérer à l'AFUJ, l'Association Francophone des Utilisateurs de Joomla : https://www.joomla.fr/association/adherer

        Commentaire


        • #5
          top, merci du partage c'est assez intéressant j'avoue..ca ouvre quelques portes
          woluweb aime ceci.
          Expert en conception et réalisation de sites Internet 100% Joomla
          www.toonetcreation.com

          Commentaire


          • #6
            Envoyé par Tortue Genial 69 Voir le message
            +1 avec cavo789 une boucle sera plus adaptée

            au passage, j'ai pas encore jeté un oeil sur le nouveau Custom Field de type SubForm, tu veux constuire quoi au final?
            Hello.

            En fait le type de champ subform n'est pas nouveau, il existe depuis la 3.6, mais n'était pas intégré aux custom fields.

            Je l'utilise dans plusieurs de mes dev et j'avais commencé un petit tuto ici..
            woluweb aime ceci.
            A tous les utilisateurs de Joomla du très Grand Est de la France et du Jura suisse
            Rejoignez le Joomla Users Groupe Alsace...
            roland_d_alsace va-t-il devenir roland_du_grand_est ?

            Commentaire


            • #7
              Tout à fait roland_d_alsace

              A un moment, aux champs personnalisés "de base", dans Joomla 3 le champ "Répétable" a été ajouté.
              Mais il ne permettait que de choisir quelques champs prédéfinis comme "texte" ou "image". Pas tous les champs persos de Joomla et aucun champ perso "installés" (genre un champ YouTube ou tous les champs de Advanced Custom Fields p ex).

              Avec J!4, le champ "répétable" a disparu et est remplacé avantageusement par le "subform", qui permet de sélectionner *n'importe quel champ perso*.
              (et en plus, on peut p ex dire pour chaque champ s'il doit apparaître sur la catégorie ou si c'est juste pour utiliser comme input pour un subform)
              Présentations : slides.woluweb.be | Coordonnées complètes : www.woluweb.be

              Un message d’erreur sur votre site Joomla... ayez le reflexe de consulter la base de connaissance : https://kb.joomla.fr

              Ce forum, vous l'aimez ? Il vous a sauvé la vie ? Vous y apprenez régulièrement ? Alors adhérer à l'AFUJ, l'Association Francophone des Utilisateurs de Joomla : https://www.joomla.fr/association/adherer

              Commentaire


              • #8
                Bonsoir à tous

                woluweb ; voici mon huiswerk, j'espère que le professeur titulaire de la classe de méthodologie sera content du travail de son jeune apprenti (préféré ).

                Code PHP:
                <?php

                /**
                 * This is an Alternate Layout of /components/com_fields/layouts/field/render.php.
                 * For an explanation of Alternate Layout for Custom Fields,
                 * see https://magazine.joomla.org/all-issues/may-2021/explore-the-core-play-with-custom-fields-to-enrich-your-content-or-your-design
                 */

                defined('_JEXEC') or die;

                #region 0. return earlier if nothing to do
                // No data? Stop
                if (!isset($displayData)) {
                    return;
                }

                $field $displayData['field'] ?? '';

                // No field? Stop
                if ('' === $field) {
                    return;
                }

                $value $field->value ?? '';

                // No value? Stop
                if ('' === $value) {
                    return;
                }

                // Get Joomla objects and initialize variables
                $app JFactory::getApplication();

                // "view" would output "article" or "category" for example
                $view $app->input->getCMD('view''');

                // "id" gives the id of the category if blog view, the id of the article if article view
                // $id = $app->input->getCMD('id', '');

                // if the view is not an article view (but a blog view or whatever)
                // then nothing will be displayed. Stop
                if ("article" !== $view) {
                    return;
                }
                #endregion

                // commented bc not needed for Alternated Layout
                /*$label = Text::_($field->label);*/

                #region 1. Prepare variables based on params
                // added for Alternated Layout

                // Get the value and convert it into an array
                $rawvalue $field->rawvalue ?? '';
                $items json_decode($rawvaluetrue);

                // Get parameters
                $showLabel $field->params->get('showlabel') ?? true;
                $labelClass $field->params->get('label_render_class') ?? '';
                $renderClass $field->params->get('render_class') ?? '';
                #endregion

                // @todo Customize "carouselWithCustomFields" with the ID of the
                // article so that it would also work on a blog view where we need a unique id for each carousel

                // https://docs.joomla.org/J4.x:Using_Bootstrap_Components_in_Joomla_4

                #region 1. Create the buttons         - Set the carouselButtons variable
                $first true;
                $i 0;
                $carouselButtons '';

                $templateCarouselButtons =
                    
                '<button class="%s" type="button" ' .
                        
                'data-bs-target="#carouselWithCustomFields" ' .
                        
                'data-bs-slide-to="%s" ' .
                        
                'aria-current="true" aria-label="%s" />';

                foreach (
                $items as $item) {
                    
                $carouselButtons .= sprintf(
                        
                $templateCarouselButtons,
                        (
                $first 'active' ''),       // Active or not
                        
                strval($i),                     // The slide-to number
                        
                strval($item['field1'] ?? '')   // The aria-label for the slide
                    
                );

                    
                $first false;
                    
                $i += 1;
                }
                #endregion

                #region 2. Create the different items - Set the carouselItems variable
                $first true;
                $carouselItems '';

                $templateCarouselItems =
                    
                '<div class="carousel-item %s" data-bs-interval="%d">' .
                        
                '<img class="d-block w-100" src="%s" />' .
                        
                '<div class="carousel-caption d-none d-md-block">' .
                            
                '<h5>%s</h5>' .
                        
                '</div>' .
                    
                '</div>';

                foreach (
                $items as $item) {
                    
                $carouselItems .= sprintf(
                        
                $templateCarouselItems,
                        (
                $first 'active' ''),                 // Active or not
                        
                (1000 * (intval($item['field2'] ?? 1))),  // The interval
                        
                $item['field3']['imagefile'] ?? '',       // The image
                        
                $item['field1'] ?? ''                     // The title (heading 5)
                    
                );

                    
                $first false;
                }
                #endregion

                #region 3. Put things together        - Set the final carouselDiv variable
                $templateCarouselDiv =
                    
                '<div id="carouselWithCustomFields" ' .
                        
                'class="carousel slide carousel-fade" data-bs-ride="carousel">' .
                        
                '<div class="carousel-indicators">%s</div>' .
                        
                '<div class="carousel-inner">%s</div>' .
                        
                '<button class="carousel-control-prev" type="button" ' .
                            
                'data-bs-target="#carouselWithCustomFields" data-bs-slide="prev"> ' .
                            
                '<span class="carousel-control-prev-icon" aria-hidden="true"></span>' .
                            
                '<span class="visually-hidden">Previous</span>' .
                        
                '</button>' .
                        
                '<button class="carousel-control-next" type="button" ' .
                            
                'data-bs-target="#carouselWithCustomFields" data-bs-slide="next">' .
                            
                '<span class="carousel-control-next-icon" aria-hidden="true"></span>' .
                            
                '<span class="visually-hidden">Next</span>' .
                        
                '</button>';
                    
                '</div>';

                $carouselDiv sprintf(
                    
                $templateCarouselDiv,
                    
                $carouselButtons,       // carousel-indicators
                    
                $carouselItems          // carousel-inner
                );
                #endregion

                #region 4. Define our CSS             - Set the carouselCSS variable
                $carouselCSS = <<<MYCSS
                /* example of CSS for bootstrap.carousel - adding a background to the carousel-caption - see https://ui.glass/generator/ for glassmorphism CSS */
                .carousel-caption {
                bottom: 40%; /* otherwise with our background too close from Indicators with the default 1.25rem */
                left: 25%; /* to make it narrower than with the default 15% */
                right: 25%; /* to make it narrower than with the default 15% */
                backdrop-filter: blur(16px) saturate(180%);
                -webkit-backdrop-filter: blur(16px) saturate(180%);
                background-color: rgba(0,0,0,0.5);
                border-radius: 12px;
                border: 1px solid rgba(255, 255, 255, 0.125);
                }
                /* by default the custom fields appear in a Unordered List. To make the carousel start on the left and hide the bullet point we use a negative margin */
                li.field-entry.mycarousel {
                margin-left: -2rem;
                }
                MYCSS;
                #endregion

                #region 5. Joomla part - Inject the carousel in the page
                use Joomla\CMS\Factory;

                // selector is necessary for the potentials Options to work
                \Joomla\CMS\HTML\HTMLHelper::_(
                    
                'bootstrap.carousel ',
                    
                '#carouselWithCustomFields',
                    [
                        
                'interval' => 3000,
                        
                'pause' => 'false'
                    
                ]
                );

                // And inject the CSS and the HTML of our carousel
                $doc Factory::getDocument();
                $doc->addStyleDeclaration($carouselCSS);
                echo 
                $carouselDiv;

                // Everything after the "return" will be ignored
                return;
                #endregion

                #region Ununeeded stuff, just needed during testing/development
                // this would render the value of the Custom Field
                echo '<span class="field-value ' $renderClass '">' $value '</span>';

                // this would render the rawvalue of the Custom Field
                echo '<span class="field-value ' $renderClass '">' $rawvalue '</span>';

                // this would render the json as numbered list
                $items json_decode($rawvaluetrue);

                foreach (
                $items as $item) {
                    echo
                      
                '<ul>'.
                         
                '<li>' $item['field1'] ?? '' '</li>' .
                         
                '<li>' $item['field2'] ?? '' '</li>' .
                         
                '<li>' $item['field3']['imagefile'] ?? '' '</li>' .
                      
                '</ul>';
                }
                #endregion
                J'ai voulu être le plus propre possible afin que, si tu publies ce code, qu'il soit lisible par un maximum de personnes.

                Le code est structuré pour montrer la progression de la logique et utilise des variables "templates" afin qu'il soit aisé de bien comprendre la différence entre la partie statique (le code HTML) et la partie dynamique (les variables qui seront injectées).

                Ces templates rendent aisé la mise à jour du code HTML sans prendre le risque de casser du code PHP.

                Le code est écrit pour être exécuté sur PHP7+ (adieu PHP 5) et, c'est un détail, pour être édité en Visual Studio Code (les blocs "region ... endregion" sont des tags supportés par vscode pour faire du "code folding"; pratique que tu es dans un fichier source tel que le tien (pas de classes; pas de fonctions, ... tout codé à-la-queue-leu-leu). Ces regions permettent de "plier" le code et donc de bien le structurer visuellement (un peu comme une table des matières).

                Voilà, je re-re-répète : c'est de la réécriture de code sans aucun test; je n'ai rien testé ni validé. Aussi il se peut qu'il y a des stuuud's à corriger ici et là.

                Bonne relecture, bons tests et au plaisir de lire le prochain chapitre de ta bible Custom Fields.
                woluweb aime ceci.
                Christophe (cavo789)
                Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be
                Logiciel gratuit de scan antivirus : https://github.com/cavo789/aesecure_quickscan (plus de 45.000 virus détectés, 700.000 fichiers sur liste blanche)​

                Commentaire


                • #9
                  salut cavo789

                  et moi qui espérait pouvoir te charrier en disant que tu avais cassé ton site...
                  ... hé ben même pas un point-virgule qui manque.
                  Le "carousel" fonctionne aussi bien qu'avant

                  Encore un tout tout grand merci.
                  Tu vas passer à la postérité dans le prochain JCM
                  cavo789 aime ceci.
                  Présentations : slides.woluweb.be | Coordonnées complètes : www.woluweb.be

                  Un message d’erreur sur votre site Joomla... ayez le reflexe de consulter la base de connaissance : https://kb.joomla.fr

                  Ce forum, vous l'aimez ? Il vous a sauvé la vie ? Vous y apprenez régulièrement ? Alors adhérer à l'AFUJ, l'Association Francophone des Utilisateurs de Joomla : https://www.joomla.fr/association/adherer

                  Commentaire


                  • #10
                    Ah cool... Ce n'était pas gagné vu les changements effectués. Reste plus qu'à trouver un codeur Joomla pour te permettre de récupérer l'ID de l'article; en vue blog.
                    Christophe (cavo789)
                    Mon blog, on y parle Docker, PHP, WSL, Markdown et plein d'autres choses : https://www.avonture.be
                    Logiciel gratuit de scan antivirus : https://github.com/cavo789/aesecure_quickscan (plus de 45.000 virus détectés, 700.000 fichiers sur liste blanche)​

                    Commentaire

                    Annonce

                    Réduire
                    Aucune annonce pour le moment.

                    Partenaire de l'association

                    Réduire

                    Hébergeur Web PlanetHoster
                    Travaille ...
                    X