{"id":234219,"date":"2023-02-15T17:52:00","date_gmt":"2023-02-15T14:52:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=234219"},"modified":"2022-11-12T00:49:08","modified_gmt":"2022-11-11T21:49:08","slug":"tutoriel-creer-un-type-de-champ-de-formulaires-de-gravite-personnalises-avances-et-comment-gerer-plusieurs-valeurs-dentree","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/tutoriel-creer-un-type-de-champ-de-formulaires-de-gravite-personnalises-avances-et-comment-gerer-plusieurs-valeurs-dentree\/","title":{"rendered":"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&rsquo;entr\u00e9e"},"content":{"rendered":"\n<p>Dans ce didacticiel, je vais vous montrer comment cr\u00e9er un type de champ Gravity Forms personnalis\u00e9 avanc\u00e9. Le champ aura plusieurs entr\u00e9es et n\u00e9cessitera un traitement sp\u00e9cial afin de stocker et d&rsquo;afficher les valeurs soumises.<\/p>\n<h2>Ce que nous ferons<\/h2>\n<p>Dans cet exemple, je suppose un exemple de propri\u00e9taire de site Web WordPress qui s&rsquo;occupe des livraisons de d\u00e9jeuners sur un lieu de travail. Le propri\u00e9taire a un formulaire pour que les gens remplissent le type de d\u00e9jeuner qu&rsquo;ils veulent et combien pour chaque jour de la semaine. Cela peut \u00eatre r\u00e9solu comme une m\u00e9thode semblable \u00e0 un tableau pour entrer un num\u00e9ro pour n&rsquo;importe quel cours \u00e0 n&rsquo;importe quel jour o\u00f9 ils veulent \u00eatre livr\u00e9s.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509da5343d.png\" data-rel=\"lightbox\" ><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509da5343d.png\" alt=\"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&#039;entr\u00e9e\" ><\/a><\/p>\n<p>Les cours sont modifiables dans les param\u00e8tres du champ dans l&rsquo;\u00e9diteur de formulaire et peuvent \u00eatre modifi\u00e9s \u00e0 tout moment. Et pour chaque soumission de formulaire, le propri\u00e9taire du site Web obtient un aper\u00e7u complet des valeurs soumises\u00a0:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dbe8f8c.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dbe8f8c.png\" alt=\"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&#039;entr\u00e9e\" ><\/a><\/p>\n<p>\u00c9videmment, ce n&rsquo;est qu&rsquo;un exemple et vous devrez probablement l&rsquo;adapter \u00e0 votre cas. Mais avec cet exemple, nous avons la chance d&rsquo;apprendre \u00e0 g\u00e9rer plusieurs entr\u00e9es dans un seul champ. Cela devrait vous donner quelques id\u00e9es sur la fa\u00e7on de g\u00e9rer votre propre type de champ personnalis\u00e9.<\/p>\n<h2>Avant de commencer \u00e0 coder<\/h2>\n<p>Avant de commencer, nous avons besoin d&rsquo;un endroit pour ajouter notre code. Vous pouvez l&rsquo;ajouter dans votre th\u00e8me <code>functions.php<\/code>ou dans votre fichier de plugin.<\/p>\n<p>La m\u00e9thode que j&rsquo;ai choisie est orient\u00e9e objet, ce qui signifie cr\u00e9er une classe qui \u00e9tend la <code>GF_Field<\/code>classe de Gravity Forms. Je recommande de mettre la classe dans un fichier s\u00e9par\u00e9 dans votre projet. Vous devez \u00e9galement v\u00e9rifier que le plugin Gravity Forms existe avant d&rsquo;inclure votre classe pour \u00e9viter de planter votre site.<\/p>\n<p>Si vous \u00eates int\u00e9ress\u00e9, vous pouvez consulter <a href=\"https:\/\/docs.gravityforms.com\/gf_field\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la documentation de Gravity Forms sur GF_Field<\/a>. Vous trouverez d&rsquo;autres fonctions et variables dont vous pourriez avoir besoin pour votre type de champ.<\/p>\n<p>En \u00e9tendant la <code>GF_Field<\/code>classe, nous pouvons simplement choisir de remplacer les fonctions que nous devons modifier. En ce qui concerne les fonctions que nous ne rempla\u00e7ons pas, Gravity Forms ex\u00e9cutera la valeur par d\u00e9faut d\u00e9finie dans <code>GF_Field<\/code>. Dans le didacticiel ci-dessous, nous allons passer en revue chaque fonction que nous devons remplacer pour notre champ personnalis\u00e9 une par une. Sans plus tarder, commen\u00e7ons !<\/p>\n<h2>Cr\u00e9ation d&rsquo;un type de champ personnalis\u00e9<\/h2>\n<p>La premi\u00e8re \u00e9tape consiste \u00e0 d\u00e9finir une classe PHP personnalis\u00e9e qui \u00e9tend <code>GF_Field<\/code>. Donnez \u00e0 la classe un nom unique et assurez-vous qu&rsquo;elle est incluse dans votre projet. Apr\u00e8s la d\u00e9finition de la classe, nous ex\u00e9cutons la <code>register()<\/code>fonction statique en <code>GF_Field<\/code>passant une instance de notre classe en param\u00e8tre. Cela initialise notre classe et enregistre le type de champ.<\/p>\n<p>La seule variable obligatoire dont vous avez besoin dans votre classe est <code>$type<\/code>. La variable de classe <code>$type<\/code>doit \u00eatre unique et est un nom de slug de votre type de champ. Dans mon exemple, je l&rsquo;ai nomm\u00e9 &lsquo; <code>food_delivery<\/code>&lsquo;.<\/p>\n<pre><code>if (class_exists('GF_Field')) {\n    class FoodDelivery extends GF_Field {\n        public $type = 'food_delivery';\n\u00a0\n        \/\/ The rest of the code is added here...\n    }\n    GF_Fields::register(new FoodDelivery());\n}<\/code><\/pre>\n<p>Avec ce petit morceau de code, notre type de champ personnalis\u00e9 doit \u00eatre ajout\u00e9 en tant que choix disponible dans l&rsquo;\u00e9diteur Gravity Forms. Par d\u00e9faut, il appara\u00eet \u00e0 la fin de la bo\u00eete &quot;Champs standard&quot;. Parce que nous n&rsquo;avons pas encore donn\u00e9 de nom \u00e0 notre champ (c&rsquo;est la prochaine \u00e9tape), le bouton est \u00e9tiquet\u00e9 comme la valeur de <code>$type<\/code>.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dd8f563.jpg\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dd8f563.jpg\" alt=\"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&#039;entr\u00e9e\" ><\/a><\/p>\n<h2>D\u00e9finir le nom du champ<\/h2>\n<p>La prochaine \u00e9tape est facile; simplement donner \u00e0 notre domaine un meilleur nom. Pour ce faire, nous red\u00e9finissons la fonction <code>get_form_editor_field_title()<\/code>. Tout ce que nous avons \u00e0 faire est de renvoyer une cha\u00eene avec le nom du champ.<\/p>\n<pre><code>public function get_form_editor_field_title() {\n    return esc_attr__('Food Delivery', 'txtdomain');\n}<\/code><\/pre>\n<p>Avec cette fonction dans notre classe, le bouton pour ajouter le champ est mis \u00e0 jour avec une bien meilleure \u00e9tiquette.<\/p>\n<h2>Modification de la cat\u00e9gorie de champ<\/h2>\n<p>Cette \u00e9tape est facultative. Par d\u00e9faut, notre type de champ personnalis\u00e9 appara\u00eet dans la case &quot;Champs standard&quot;, mais nous pouvons le modifier. Supposons que nous voulions qu&rsquo;il apparaisse \u00e0 la place dans la bo\u00eete &quot;Champs avanc\u00e9s&quot;.<\/p>\n<p>Pour changer la cat\u00e9gorie dans laquelle nous voulons que le champ apparaisse, nous rempla\u00e7ons la fonction <code>get_form_editor_button()<\/code>. Nous devons retourner un tableau associatif avec deux \u00e9l\u00e9ments. En tant que valeur de la cl\u00e9 &lsquo; <code>group<\/code>&lsquo;, vous fournissez le nom interne de la cat\u00e9gorie dans laquelle vous souhaitez que le bouton apparaisse. Les options disponibles ici sont &lsquo; <code>standard_fields<\/code>&lsquo;, &lsquo; <code>advanced_fields<\/code>&lsquo;, &lsquo; <code>post_fields<\/code>&lsquo; ou &lsquo; <code>pricing_fields<\/code>&lsquo;. (Vous pouvez \u00e9galement cr\u00e9er votre propre cat\u00e9gorie, mais cela n&rsquo;est pas couvert ici). Le deuxi\u00e8me \u00e9l\u00e9ment du tableau a besoin de la cl\u00e9 &lsquo; <code>text<\/code>&lsquo; et pour cela nous renvoyons simplement le nom du champ en appelant <code>get_form_editor_field_title()<\/code>. C&rsquo;est la fonction que nous venons de cr\u00e9er ci-dessus.<\/p>\n<pre><code>public function get_form_editor_button() {\n    return [\n        'group' =&gt; 'advanced_fields',\n        'text'  =&gt; $this-&gt;get_form_editor_field_title(),\n    ];\n}<\/code><\/pre>\n<p>Maintenant, le bouton pour ajouter notre type de champ personnalis\u00e9 est d\u00e9plac\u00e9 dans la case &quot;Champs avanc\u00e9s&quot;.<\/p>\n<h2>Activation des param\u00e8tres de champ<\/h2>\n<p>Si vous avez essay\u00e9 d&rsquo;ajouter le type de champ dans un formulaire, vous avez peut-\u00eatre remarqu\u00e9 qu&rsquo;il n&rsquo;y a aucun param\u00e8tre. Vous ne pouvez m\u00eame pas modifier l&rsquo;\u00e9tiquette. La fa\u00e7on dont cela fonctionne est que tous les types de param\u00e8tres sont r\u00e9ellement l\u00e0, ils sont simplement tous cach\u00e9s avec CSS par Gravity Forms. Nous devons d\u00e9finir individuellement les param\u00e8tres que nous voulons activer, et Gravity Forms affichera alors les param\u00e8tres choisis pour nous.<\/p>\n<p>Nous devons d\u00e9finir la fonction <code>get_form_editor_field_settings()<\/code>et renvoyer un tableau de tous les param\u00e8tres que nous ne voulons pas masquer pour notre type de champ. Les param\u00e8tres que vous souhaitez ajouter d\u00e9pendent enti\u00e8rement de vous et de votre projet. Gardez \u00e0 l&rsquo;esprit que votre champ doit prendre en charge tous les param\u00e8tres que vous activez, sinon cela n&rsquo;a aucun sens d&rsquo;afficher un param\u00e8tre pour celui-ci.<\/p>\n<p>J&rsquo;ai cr\u00e9\u00e9 un aper\u00e7u rapide des noms des param\u00e8tres ci-dessous. C&rsquo;est loin d&rsquo;\u00eatre une liste compl\u00e8te &#8211; car il y a beaucoup de param\u00e8tres qui ne sont pratiquement utiles que pour des types de champs tr\u00e8s sp\u00e9cifiques. Par exemple, le format de t\u00e9l\u00e9phone, le format de date\/heure et tout un tas de param\u00e8tres li\u00e9s aux champs de publication et aux champs de tarification.<\/p>\n<h4>Onglet G\u00e9n\u00e9ral<\/h4>\n<ul>\n<li>Libell\u00e9 du champ\u00a0:<code>label_setting<\/code><\/li>\n<li>Descriptif du champ\u00a0:<code>description_setting<\/code><\/li>\n<li>Les choix:<code>choices_setting<\/code><\/li>\n<li>Obligatoire:<code>rules_setting<\/code><\/li>\n<li>Pas de doublons\u00a0:<code>duplicate_setting<\/code><\/li>\n<li>Activer les colonnes\u00a0:<code>columns_setting<\/code><\/li>\n<li>Activer le choix &quot;tout s\u00e9lectionner&quot;\u00a0:<code>select_all_choices_setting<\/code><\/li>\n<li>Activer le choix &quot;autre&quot;:<code>other_choice_setting<\/code><\/li>\n<\/ul>\n<h4>Onglet Apparence<\/h4>\n<ul>\n<li>Espace r\u00e9serv\u00e9\u00a0:<code>placeholder_setting<\/code><\/li>\n<li>Visibilit\u00e9 de l&rsquo;\u00e9tiquette de champ et emplacement de la description\u00a0:<code>label_placement_setting<\/code><\/li>\n<li>Message de validation personnalis\u00e9\u00a0:<code>error_message_setting<\/code><\/li>\n<li>Classe CSS personnalis\u00e9e\u00a0:<code>css_class_setting<\/code><\/li>\n<li>Taille du champ:<code>size_setting<\/code><\/li>\n<\/ul>\n<h4>Onglet Avanc\u00e9<\/h4>\n<ul>\n<li>Libell\u00e9 du champ Admin\u00a0:<code>admin_label_setting<\/code><\/li>\n<li>Valeur par d\u00e9faut:<code>default_value_setting<\/code><\/li>\n<li>Activer la saisie du mot de passe\u00a0:<code>password_field_setting<\/code><\/li>\n<li>Forcer SSL\u00a0:<code>force_ssl_field_setting<\/code><\/li>\n<li>Visibilit\u00e9:<code>visibility_setting<\/code><\/li>\n<li>Autoriser le remplissage dynamique du champ\u00a0:<code>prepopulate_field_setting<\/code><\/li>\n<li>Activer la logique conditionnelle\u00a0:<code>conditional_logic_field_setting<\/code><\/li>\n<li>Activer la logique conditionnelle de la page\u00a0:<code>conditional_logic_page_setting<\/code><\/li>\n<\/ul>\n<p>Comme pour notre exemple, les plus importants sont l&rsquo;\u00e9tiquette du champ, la description, les choix et si oui ou non le champ est obligatoire ou non. Nous autorisons \u00e9galement les param\u00e8tres pour la classe CSS, le message de validation personnalis\u00e9 et la logique conditionnelle.<\/p>\n<pre><code>public function get_form_editor_field_settings() {\n    return [\n        'label_setting',\n        'choices_setting',\n        'description_setting',\n        'rules_setting',\n        'error_message_setting',\n        'css_class_setting',\n        'conditional_logic_field_setting'\n    ];\n}<\/code><\/pre>\n<p>Actualisez l&rsquo;\u00e9diteur de formulaire et vous devriez maintenant voir tous les param\u00e8tres et onglets choisis appara\u00eetre dans notre champ. Tous les param\u00e8tres sont g\u00e9r\u00e9s et enregistr\u00e9s automatiquement par Gravity Forms.<\/p>\n<p>Allez-y et ajoutez quelques \u00e9l\u00e9ments dans la liste des choix afin que nous ayons quelque chose avec quoi travailler. Voici ce que j&rsquo;ai mis en place \u00e0 titre d&rsquo;exemple :<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509df36138.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509df36138.png\" alt=\"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&#039;entr\u00e9e\" ><\/a><\/p>\n<h2>D\u00e9finition des choix par d\u00e9faut personnalis\u00e9s<\/h2>\n<p>Si vous avez l&rsquo;habitude d&rsquo;utiliser, par exemple, des boutons radio ou des cases \u00e0 cocher dans Gravity Forms, vous avez probablement remarqu\u00e9 qu&rsquo;ils sont accompagn\u00e9s de choix tels que &quot;First Choice&quot;, &quot;Second Choice&quot;, &quot;Third Choice&quot;. Il s&rsquo;agit du comportement par d\u00e9faut de Gravity Forms si aucun choix n&rsquo;a \u00e9t\u00e9 enregistr\u00e9 (avant) et cela ne se d\u00e9clenche que sur ces types de champs sp\u00e9cifiques. Mais pour notre type de champ personnalis\u00e9, aucun choix ne sera rempli. Cela le rend un peu lourd, car vous n&rsquo;obtiendrez pas le bouton &quot;+&quot; pour ajouter un autre choix. Vous devez utiliser le bouton &quot;Ajouter en bloc\/choix pr\u00e9d\u00e9finis&quot;, y ajouter des choix, et apr\u00e8s cela, vous avez acc\u00e8s aux boutons &quot;+&quot; pour ajouter des choix. Mais il est facile de d\u00e9finir des choix personnalis\u00e9s &#8211; tout ce dont vous avez besoin est de d\u00e9finir une variable de tableau de classe<code>public $choices<\/code>et Gravity Forms g\u00e9n\u00e9rera automatiquement des choix pr\u00e9d\u00e9finis dans votre champ lorsque vous l&rsquo;ajouterez \u00e0 vos formulaires.<\/p>\n<p>Remarque: Il s&rsquo;agit d&rsquo;une variable de classe, que vous pouvez ajouter en haut de la classe, juste en dessous de <code>public $type<\/code>. Chaque choix doit \u00eatre un tableau, avec le choix comme valeur de la cl\u00e9 &lsquo; <code>text<\/code>&lsquo;.<\/p>\n<pre><code>public $choices = [\n    [ 'text' =&gt; 'Food Choice 1' ],\n    [ 'text' =&gt; 'Food Choice 2' ],\n    [ 'text' =&gt; 'Food Choice 3' ],\n];<\/code><\/pre>\n<p>Gardez \u00e0 l&rsquo;esprit que si vous avez d\u00e9j\u00e0 ajout\u00e9 le champ au formulaire, il ne remplira pas r\u00e9troactivement les choix. Cela n&rsquo;entre en vigueur que lorsque vous ajoutez un nouveau champ au formulaire.<\/p>\n<p><strong>Note<\/strong>: Dans Gravity Forms, il semble possible d&rsquo;ajouter \u00e9galement les touches &lsquo; <code>value<\/code>&lsquo; \u00e0 chaque choix. Mais je n&rsquo;ai pas r\u00e9ussi \u00e0 faire fonctionner cela &#8211; les valeurs deviendront automatiquement les m\u00eames que le texte de choix.<\/p>\n<h2>D\u00e9finition de la valeur du champ en tant que tableau<\/h2>\n<p>La prochaine \u00e9tape est assez simple, mais n\u00e9cessaire. Les valeurs par d\u00e9faut des champs dans Gravity Forms sont des cha\u00eenes. Nous avons besoin que la valeur soit un tableau car nous travaillons avec plusieurs entr\u00e9es. Pour ce faire, nous d\u00e9finissons la fonction <code>is_value_submission_array()<\/code>et renvoyons <code>true<\/code>.<\/p>\n<pre><code>public function is_value_submission_array() {\n    return true;\n}<\/code><\/pre>\n<p>Cela garantit que nous pouvons travailler correctement avec la valeur saisie de nos multiples entr\u00e9es.<\/p>\n<h2>Rendu de la sortie de champ<\/h2>\n<p>Lorsqu&rsquo;il s&rsquo;agit de rendre la sortie du champ, il y a quelques points \u00e0 prendre en compte.<\/p>\n<p>Tout d&rsquo;abord, vous devez choisir entre deux fonctions\u00a0; <code>get_field_input()<\/code>ou <code>get_field_content()<\/code>. Dans la premi\u00e8re m\u00e9thode, Gravity Forms affiche automatiquement l&rsquo;\u00e9l\u00e9ment de la liste d&#8217;emballage, l&rsquo;\u00e9tiquette, la description et le conteneur du message d&rsquo;erreur de validation dans votre champ et vous ne contr\u00f4lez que la sortie du champ interne. Avec la deuxi\u00e8me m\u00e9thode, rien de tout cela ne se produit et vous contr\u00f4lez davantage la sortie du champ. Cependant, vous devez afficher manuellement l&rsquo;\u00e9tiquette, la description et les messages d&rsquo;erreur. La premi\u00e8re m\u00e9thode, <code>get_field_input()<\/code>, convient parfaitement dans la plupart des cas.<\/p>\n<p>La deuxi\u00e8me chose \u00e0 savoir est que la fonction de rendu du champ affecte trois emplacements diff\u00e9rents. Les trois sont le rendu de la sortie du champ dans l&rsquo;interface, l&rsquo;aper\u00e7u du champ dans l&rsquo;\u00e9diteur de formulaire et enfin le champ lors de la modification d&rsquo;une entr\u00e9e. Heureusement, Gravity Forms propose des fonctions pour d\u00e9terminer facilement \u00e0 quelle vue nous en sommes. Habituellement, vous rendrez le champ de la m\u00eame mani\u00e8re dans les trois cas. Mais parce que le rendu d&rsquo;une grande table avec beaucoup d&rsquo;entr\u00e9es devient inutilement maladroit dans l&rsquo;\u00e9diteur de formulaire, j&rsquo;ai choisi de rendre le champ diff\u00e9remment dans l&rsquo;\u00e9diteur de formulaire.<\/p>\n<p>Et enfin, nous devons nous assurer que toutes les entr\u00e9es re\u00e7oivent un <code>name<\/code>attribut appropri\u00e9 afin que Gravity Forms puisse collecter sa valeur lors de la soumission du formulaire. Toutes les entr\u00e9es dans Gravity Forms ont besoin d&rsquo; <code>name<\/code>attributs qui suivent cette r\u00e8gle\u00a0: <code>name=\"input_{FIELD_ID}\"<\/code>(les champs \u00e0 s\u00e9lection multiple utilisent un ID suppl\u00e9mentaire, mais nous n&rsquo;avons pas besoin de nous en pr\u00e9occuper pour notre cas). Nous avons acc\u00e8s au champ ID car il s&rsquo;agit d&rsquo;une variable de classe (de <code>GF_Field<\/code>). Mais dans notre cas, nous avons dit \u00e0 Gravity Forms que la valeur est un tableau et non une valeur singuli\u00e8re (\u00e9tape pr\u00e9c\u00e9dente), nous ajoutons donc des crochets apr\u00e8s l&rsquo;attribut name ; <code>name=\"input_{FIELD_ID}[]\"<\/code>. Ainsi, si le champ a l&rsquo;ID 4 dans un formulaire, l&rsquo;attribut name doit \u00eatre &quot; <code>input_4[]<\/code>&quot;.<\/p>\n<p>J&rsquo;opte pour l&rsquo;utilisation <code>get_field_input()<\/code>qui vient avec trois param\u00e8tres. Le premier param\u00e8tre est l&rsquo;objet formulaire, dont nous n&rsquo;avons pas vraiment besoin pour notre exemple. Le deuxi\u00e8me param\u00e8tre est la valeur actuelle. Il peut s&rsquo;agir de la valeur du champ \u00e0 partir de <code>$_POST<\/code>laquelle le formulaire a \u00e9t\u00e9 soumis, mais sans succ\u00e8s. Nous pouvons conserver les valeurs soumises pr\u00e9c\u00e9demment. Ou si la fonction est en cours d&rsquo;ex\u00e9cution lors de la modification d&rsquo;une entr\u00e9e, la valeur sera la valeur stock\u00e9e \u00e0 partir de la soumission. Nous traiterons la valeur de plus pr\u00e8s plus tard. Et le troisi\u00e8me param\u00e8tre est l&rsquo;objet d&rsquo;entr\u00e9e, dont nous n&rsquo;aurons pas non plus besoin pour notre exemple.<\/p>\n<p>Commen\u00e7ons par impl\u00e9menter <code>get_field_input()<\/code>ce qui attend le rendu final sous forme de cha\u00eene. D\u00e8s le d\u00e9part, je d\u00e9cide de renvoyer une cha\u00eene vide si nous sommes \u00e0 l&rsquo;int\u00e9rieur de l&rsquo;\u00e9diteur de formulaire, car je ne veux pas afficher le tableau complet dans cette vue. Nous pouvons utiliser la m\u00e9thode <code>$this-&gt;is_form_editor()<\/code>pour v\u00e9rifier si nous sommes ou non dans l&rsquo;\u00e9dition du formulaire. Vous pouvez choisir d&rsquo;ignorer cela ou de rendre autre chose si vous souhaitez un aper\u00e7u du champ dans l&rsquo;\u00e9diteur de formulaire.<\/p>\n<pre><code>public function get_field_input($form, $value = '', $entry = null) {\n    if ($this-&gt;is_form_editor()) {\n        return '';\n    }\n    \/\/ .. Rest of code for frontend and edit entry here...\n}<\/code><\/pre>\n<p>L&rsquo;\u00e9tape suivante consiste \u00e0 cr\u00e9er le code HTML d&rsquo;un tableau qui boucle sur un tableau de jours pour g\u00e9n\u00e9rer les colonnes et les lignes pour chaque \u00e9l\u00e9ment de cours. Mais parce que nous avons besoin d&rsquo;acc\u00e9der au tableau de jours (colonnes de table) \u00e0 plusieurs endroits, nous devons le d\u00e9finir comme une variable de classe, le rendant accessible \u00e0 partir de toutes les fonctions qu&rsquo;il contient. Je d\u00e9finis une variable de classe <code>$delivery_days<\/code>avec un tableau des jours pour lesquels je souhaite proposer la livraison.<\/p>\n<pre><code>class FoodDelivery extends GF_Field {\n    public $type = 'food_delivery';\n\u00a0\n    private $delivery_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];\n\u00a0\n    public function get_form_editor_field_title() {\n        ...\n}<\/code><\/pre>\n<p>C&rsquo;est juste un exemple! Vous voudrez peut-\u00eatre r\u00e9cup\u00e9rer le tableau pour les colonnes d&rsquo;un autre endroit qui n&rsquo;est pas cod\u00e9 en dur.<\/p>\n<p>Revenons <code>get_field_input()<\/code>et construisons notre table avec des entr\u00e9es. D&rsquo;abord, je boucle sur la variable de classe et g\u00e9n\u00e8re les en-t\u00eates de tableau. Ensuite, je boucle sur les choix entr\u00e9s dans le champ de r\u00e9glage pour les choix. Ceci est accessible \u00e0 partir de la variable de classe (de <code>GF_Field<\/code>) <code>$this-&gt;choices<\/code>. Pour chaque choix, je rends une entr\u00e9e avec les attributs de nom propre. Nous avons acc\u00e8s \u00e0 l&rsquo;ID du champ \u00e0 partir <code>GF_Field<\/code>de la variable de classe de <code>$this-&gt;id<\/code>.<\/p>\n<pre><code>public function get_field_input($form, $value = '', $entry = null) {\n    if ($this-&gt;is_form_editor()) {\n        return '';\n    }\n\u00a0\n    $id = (int) $this-&gt;id;\n    $table = '&lt;table class=\"delivery-table\"&gt;&lt;tbody&gt;&lt;tr&gt;';\n    $table .= '&lt;th&gt;'. __('Course', 'txtdomain'). '&lt;\/th&gt;';\n    foreach ($this-&gt;delivery_days as $day) {\n        $table .= '&lt;th&gt;'. $day. '&lt;\/th&gt;';\n    }\n    $table .= '&lt;\/tr&gt;';\n\u00a0\n    foreach ($this-&gt;choices as $course) {\n        $table .= '&lt;tr&gt;';\n        $table .= '&lt;td&gt;'. $course['text']. '&lt;\/td&gt;';\n        foreach ($this-&gt;delivery_days as $day) {\n            $table .= '&lt;td&gt;&lt;input type=\"number\" size=\"1\" name=\"input_'. $id. '[]\" \/&gt;&lt;\/td&gt;';\n        }\n        $table .= '&lt;\/tr&gt;';\n    }\n    $table .= '&lt;\/tbody&gt;&lt;\/table&gt;';\n\u00a0\n    return $table;\n}<\/code><\/pre>\n<p>Avec ce code en place, nous devrions obtenir une belle table rendue pour notre type de champ en frontend\u00a0! \u00c9videmment, le HTML d\u00e9pend enti\u00e8rement de vous, ce n&rsquo;est qu&rsquo;un exemple de base.<\/p>\n<p><strong>Nous laissons cette fonction pour l&rsquo;instant, mais nous y reviendrons plus tard pour g\u00e9rer la valeur soumise !<\/strong><\/p>\n<h2>Stocker correctement la valeur<\/h2>\n<p>\u00c0 partir de maintenant, Gravity Forms enregistrera notre champ sous la forme d&rsquo;un tableau unidimensionnel rempli avec les valeurs saisies et les cha\u00eenes vides o\u00f9 l&rsquo;entr\u00e9e \u00e9tait vide. Il n&rsquo;y a aucune information sur le jour ou le choix auquel la valeur appartient, autre que l&rsquo;index. Nous devons transformer ce tableau unidimensionnel en un tableau associatif multidimensionnel o\u00f9 nous stockons le jour et l&rsquo;\u00e9tiquette de choix. Nous pouvons alors facilement acc\u00e9der \u00e0 la valeur num\u00e9rique stock\u00e9e, par exemple <code>$value['Ham sandwich']['Monday']<\/code>. Apr\u00e8s cette transformation de tableau, nous devons \u00e9galement s\u00e9rialiser le tableau afin que Gravity Forms puisse stocker correctement la valeur dans la base de donn\u00e9es.<\/p>\n<p>Nous devrons transformer ce tableau de valeurs \u00e0 plusieurs endroits, je d\u00e9finirai donc une fonction distincte pour cela. La fonction accepte le tableau unidimensionnel et le transforme en un tableau multidimensionnel avec les valeurs stock\u00e9es pour les jours et les choix\u00a0:<\/p>\n<pre><code>private function translateValueArray($value) {\n    if (empty($value)) {\n        return [];\n    }\n    $table_value = [];\n    $counter = 0;\n    foreach ($this-&gt;choices as $course) {\n        foreach ($this-&gt;delivery_days as $day) {\n            $table_value[$course['text']][$day] = $value[$counter++];\n        }\n    }\n    return $table_value;\n}<\/code><\/pre>\n<p>Cela stockera les noms de jour et les choix directement dans la valeur du champ. Proc\u00e9der ainsi permet de modifier les choix ult\u00e9rieurement sans casser les anciennes entr\u00e9es.<\/p>\n<p>Passons maintenant au remplacement de la fonction qui g\u00e8re le stockage de la valeur soumise\u00a0; <code>get_value_save_entry()<\/code>. Il est livr\u00e9 avec cinq param\u00e8tres mais nous n&rsquo;avons besoin que du premier qui est la valeur soumise. \u00c0 l&rsquo;int\u00e9rieur de la fonction, nous transmettons la valeur \u00e0 notre fonction personnalis\u00e9e ci-dessus, s\u00e9rialisons son retour et renvoyons enfin la nouvelle valeur.<\/p>\n<pre><code>public function get_value_save_entry($value, $form, $input_name, $lead_id, $lead) {\n    if (empty($value)) {\n        $value = '';\n    } else {\n        $table_value = $this-&gt;translateValueArray($value);\n        $value = serialize($table_value);\n    }\n    return $value;\n}<\/code><\/pre>\n<p>\u00c0 ce stade, Gravity Forms stockera avec succ\u00e8s nos valeurs exactement comme nous les voulons! Cependant, la valeur stock\u00e9e est maintenant un tableau s\u00e9rialis\u00e9 que Gravity Forms se fera un plaisir d&rsquo;\u00e9cho directement. Nous devons impl\u00e9menter des fonctions pour le transformer d&rsquo;un vilain tableau s\u00e9rialis\u00e9 en une jolie sortie partout o\u00f9 nous en avons besoin.<\/p>\n<h2>Affichage de la valeur soumise<\/h2>\n<p>Il y a trois endroits o\u00f9 nous devons changer la sortie de la valeur de notre champ\u00a0; la liste des entr\u00e9es, en regardant une seule entr\u00e9e, et dans les balises de fusion de Gravity Forms. Les balises de fusion sont le plus souvent utilis\u00e9es dans les notifications par e-mail. Par exemple <code>{all_fields}<\/code>, une balise de fusion affiche les valeurs compl\u00e8tes du formulaire soumis dans les e-mails.<\/p>\n<p>\u00c9tant donn\u00e9 que nous rendons la m\u00eame sortie dans trois cas diff\u00e9rents, il est logique de cr\u00e9er une fonction distincte pour celle-ci. J&rsquo;ai d\u00e9fini une fonction personnalis\u00e9e qui accepte la valeur\u00a0; le tableau multidimensionnel non s\u00e9rialis\u00e9, en param\u00e8tre. La fonction construit ensuite du code HTML qui affiche le tableau de mani\u00e8re jolie et renvoie la cha\u00eene. J&rsquo;ai opt\u00e9 pour une <code>&lt;ul&gt;<\/code>liste imbriqu\u00e9e, mais vous pouvez modifier la sortie comme vous le souhaitez.<\/p>\n<pre><code>private function prettyListOutput($value) {\n    $str = '&lt;ul&gt;';\n    foreach ($value as $course =&gt; $days) {\n        $week = '';\n        foreach ($days as $day =&gt; $delivery_number) {\n            if (!empty($delivery_number)) {\n                $week .= '&lt;li&gt;'. $day. ': '. $delivery_number. '&lt;\/li&gt;';\n            }\n        }\n        \/\/ Only add week if there were any requests at all\n        if (!empty($week)) {\n            $str .= '&lt;li&gt;&lt;h3&gt;'. $course. '&lt;\/h3&gt;&lt;ul class=\"days\"&gt;'. $week. '&lt;\/ul&gt;&lt;\/li&gt;';\n        }\n    }\n    $str .= '&lt;\/ul&gt;';\n    return $str;\n}<\/code><\/pre>\n<p>Super, commen\u00e7ons par le premier: la liste des entr\u00e9es: <code>get_value_entry_list()<\/code>. Vous pouvez choisir de sortir la sortie compl\u00e8te ici, mais cela peut devenir assez maladroit et long pour la vue de liste, j&rsquo;ai donc opt\u00e9 pour simplement renvoyer une cha\u00eene fixe qui explique que l&rsquo;utilisateur doit entrer dans les d\u00e9tails de l&rsquo;entr\u00e9e pour voir la vue d&rsquo;ensemble compl\u00e8te.<\/p>\n<pre><code>public function get_value_entry_list($value, $entry, $field_id, $columns, $form) {\n    return __('Enter details to see delivery details', 'txtdomain');\n}<\/code><\/pre>\n<p>Cela d\u00e9pend bien s\u00fbr enti\u00e8rement de vous, vous pouvez opter pour n&rsquo;afficher que le premier x nombre de caract\u00e8res par exemple.<\/p>\n<p>La deuxi\u00e8me fonction est celle affectant la vue d&rsquo;une seule entr\u00e9e<code>get_value_entry_detail()<\/code>\u00a0:<\/p>\n<pre><code>public function get_value_entry_detail($value, $currency = '', $use_text = false, $format = 'html', $media = 'screen') {\n    $value = maybe_unserialize($value);     \n    if (empty($value)) {\n        return '';\n    }\n    $str = $this-&gt;prettyListOutput($value);\n    return $str;\n}<\/code><\/pre>\n<p>Nous d\u00e9s\u00e9rialisons simplement le tableau avec la fonction de WordPress <code>[maybe_unserialize](https:\/\/developer.wordpress.org\/reference\/functions\/maybe_unserialize\/)()<\/code>et renvoyons la sortie de cha\u00eene de notre fonction personnalis\u00e9e.<\/p>\n<p>La derni\u00e8re fonction affecte les balises de fusion et s&rsquo;assure que la valeur de notre champ s&rsquo;affiche \u00e9galement bien dans les e-mails\u00a0: <code>get_value_merge_tag()<\/code>.<\/p>\n<pre><code>public function get_value_merge_tag($value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br) {\n    return $this-&gt;prettyListOutput($value);\n}<\/code><\/pre>\n<p>Notez que nous n&rsquo;aurons pas besoin de d\u00e9s\u00e9rialiser la valeur \u00e0 l&rsquo;int\u00e9rieur de cette fonction.<\/p>\n<p>Avec ces trois fonctions en place, toutes les valeurs soumises devraient \u00eatre jolies partout\u00a0! Par exemple, lors de l&rsquo;affichage d&rsquo;une entr\u00e9e soumise\u00a0:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dbe8f8c.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-153179-61e509dbe8f8c.png\" alt=\"Tutoriel\u00a0: cr\u00e9er un type de champ de formulaires de gravit\u00e9 personnalis\u00e9s avanc\u00e9s et comment g\u00e9rer plusieurs valeurs d&#039;entr\u00e9e\" ><\/a><\/p>\n<p>Cependant, il manque une chose importante! \u00c0 ce stade, nos entr\u00e9es ne conservent pas les valeurs pr\u00e9c\u00e9demment soumises et c&rsquo;est plut\u00f4t mauvais.<\/p>\n<h2>Faire en sorte que nos entr\u00e9es conservent la valeur pr\u00e9c\u00e9demment soumise<\/h2>\n<p>Il existe principalement deux cas o\u00f9 nous devons nous assurer que les entr\u00e9es conservent les valeurs pr\u00e9c\u00e9demment soumises. Le premier cas est lorsqu&rsquo;une soumission de formulaire a \u00e9chou\u00e9 (par exemple, l&rsquo;utilisateur a oubli\u00e9 un champ obligatoire). \u00c0 l&rsquo;heure actuelle, toutes nos entr\u00e9es perdent toutes les valeurs pr\u00e9c\u00e9demment saisies et l&rsquo;utilisateur doit saisir \u00e0 nouveau toutes les valeurs. Deuxi\u00e8mement, lorsque le propri\u00e9taire du site modifie une entr\u00e9e, les entr\u00e9es ne sont pas renseign\u00e9es avec les valeurs soumises \u00e0 partir de la soumission, ce qui rend quasiment impossible la modification correcte des valeurs.<\/p>\n<p>Pour r\u00e9soudre ce probl\u00e8me, nous retournons \u00e0 la fonction <code>get_field_input()<\/code>. Le deuxi\u00e8me param\u00e8tre de cette fonction est la valeur. Mais rappelez-vous que cette fonction affecte \u00e0 la fois le rendu frontal et l&rsquo;\u00e9dition d&rsquo;entr\u00e9e. Ceci est important car la valeur stock\u00e9e est diff\u00e9rente dans ces deux cas. Si nous sommes \u00e0 l&rsquo;interface et que nous traitons la soumission du formulaire, la valeur est au format du tableau unidimensionnel mentionn\u00e9 pr\u00e9c\u00e9demment. Et si nous modifions une entr\u00e9e, la valeur est au format d&rsquo;un tableau multidimensionnel s\u00e9rialis\u00e9. Nous devons donc traduire correctement la valeur fournie dans <code>get_field_input()<\/code>pour acc\u00e9der facilement aux valeurs r\u00e9elles.<\/p>\n<pre><code>public function get_field_input($form, $value = '', $entry = null) {\n    if ($this-&gt;is_form_editor()) {\n        return '';\n    }\n\u00a0\n    $id = (int) $this-&gt;id;\n    if ($this-&gt;is_entry_detail()) {\n        $table_value = maybe_unserialize($value);\n    } else {\n        $table_value = $this-&gt;translateValueArray($value);\n    }\n\u00a0\n    $table = '&lt;table class=\"delivery-table\"&gt;&lt;tbody&gt;&lt;tr&gt;';\n    ...\n}<\/code><\/pre>\n<p>Dans le code ci-dessus, avant de commencer \u00e0 cr\u00e9er le HTML pour la sortie du champ, nous cr\u00e9ons une variable <code>$table_value<\/code>qui contient la valeur correctement traduite. Nous utilisons <code>GF_Field<\/code>la fonction <code>is_entry_detail()<\/code>de pour v\u00e9rifier si nous modifions ou non une entr\u00e9e. Et puis pour nos entr\u00e9es, il est facile d&rsquo;acc\u00e9der aux valeurs appropri\u00e9es et de les d\u00e9finir comme <code>value<\/code>attributs des entr\u00e9es\u00a0:<\/p>\n<pre><code>...\nforeach ($this-&gt;delivery_days as $day) {\n    $table .= '&lt;td&gt;&lt;input type=\"number\" size=\"1\" name=\"input_'. $id. '[]\" value=\"'. $table_value[$course['text']][$day]. '\" \/&gt;&lt;\/td&gt;';\n}\n...<\/code><\/pre>\n<p>Avec la mise \u00e0 jour ci-dessus <code>get_field_input()<\/code>, toutes nos entr\u00e9es personnalis\u00e9es doivent toujours \u00eatre renseign\u00e9es avec la valeur pr\u00e9c\u00e9dente\u00a0; qu&rsquo;il s&rsquo;agisse de modifier une entr\u00e9e ou de r\u00e9essayer de soumettre un formulaire.<\/p>\n<p>\u00c0 ce stade, tout ce qui concerne le rendu et le stockage de nos valeurs est termin\u00e9 et fonctionne pleinement. Mais il y a encore une chose que nous devons absolument corriger.<\/p>\n<h2>Faire passer notre champ de validation &quot;obligatoire&quot;<\/h2>\n<p>Gravity Forms a des contr\u00f4les pour voir si la valeur d&rsquo;un champ est vide ou non. Cela est souvent n\u00e9cessaire lorsque le champ est d\u00e9fini comme requis. Lorsqu&rsquo;un champ est obligatoire, vous ne pouvez pas soumettre le formulaire s&rsquo;il est vide, n&rsquo;est-ce pas\u00a0? Le probl\u00e8me pour nous est que nous avons plusieurs entr\u00e9es et nous voulons permettre \u00e0 certaines d&rsquo;entre elles d&rsquo;\u00eatre vides. Cela devient un probl\u00e8me si notre champ est d\u00e9fini sur requis. Malheureusement, Gravity Forms interpr\u00e8te mal &quot;est-ce vide&quot; et exige que toutes les entr\u00e9es soient remplies. Nous devons donc ajouter une r\u00e8gle qui dit que si au moins une de nos nombreuses entr\u00e9es est remplie, la valeur totale du champ n&rsquo;est pas vide.<\/p>\n<p>La derni\u00e8re fonction que nous devons remplacer dans notre classe est <code>is_value_submission_empty()<\/code>. Nous obtenons uniquement l&rsquo;ID de formulaire en tant que param\u00e8tre de cette fonction, nous devons donc extraire la valeur du champ en utilisant la fonction Gravity Forms pour l&rsquo;extraire du <code>$_POST<\/code>tableau\u00a0: <code>rgpost('input_&lt;FIELD ID&gt;')<\/code>. Le retour devrait \u00eatre le tableau unidimensionnel que nous avons vu auparavant. Tout ce que nous avons \u00e0 faire est de parcourir le tableau et de revenir <code>false<\/code>si nous trouvons une valeur quelque part. Sinon on revient <code>true<\/code>car la valeur du champ est en effet compl\u00e8tement vide.<\/p>\n<pre><code>public function is_value_submission_empty($form_id) {\n    $value = rgpost('input_'. $this-&gt;id);\n    foreach ($value as $input) {\n        if (strlen(trim($input)) &gt; 0) {\n            return false;\n        }\n    }\n    return true;\n}<\/code><\/pre>\n<p>Avec la fonction ci-dessus en place, notre champ n&rsquo;\u00e9chouera pas la soumission s&rsquo;il est d\u00e9fini sur requis et qu&rsquo;au moins une entr\u00e9e est remplie.<\/p>\n<h2>Conclusion et code final<\/h2>\n<p>Ce didacticiel vous a montr\u00e9 en d\u00e9tail comment cr\u00e9er votre propre type de champ avanc\u00e9 personnalis\u00e9 pour Gravity Forms. M\u00eame si votre projet est diff\u00e9rent de mon exemple, j&rsquo;esp\u00e8re que vous avez des conseils et des a-ha en cours de route. Je trouve que la documentation de Gravity Forms fait d\u00e9faut dans certains cas, et c&rsquo;est le r\u00e9sultat de beaucoup d&rsquo;essais et d&rsquo;erreurs\u00a0! En tout cas, j&rsquo;esp\u00e8re que cela vous a \u00e9t\u00e9 utile !<\/p>\n<p>Pour r\u00e9f\u00e9rence, voici le code complet dans son int\u00e9gralit\u00e9\u00a0:<\/p>\n<pre><code>if (class_exists('GF_Field')) {\n    class FoodDelivery extends GF_Field {\n        public $type = 'food_delivery';\n\u00a0\n        public $choices = [\n            [ 'text' =&gt; 'Food Choice 1' ],\n            [ 'text' =&gt; 'Food Choice 2' ],\n            [ 'text' =&gt; 'Food Choice 3' ],\n        ];\n\u00a0\n        private $delivery_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];\n\u00a0\n        public function get_form_editor_field_title() {\n            return esc_attr__('Food Delivery', 'txtdomain');\n        }\n\u00a0\n        public function get_form_editor_button() {\n            return [\n                'group' =&gt; 'advanced_fields',\n                'text'  =&gt; $this-&gt;get_form_editor_field_title(),\n            ];\n        }\n\u00a0\n        public function get_form_editor_field_settings() {\n            return [\n                'label_setting',\n                'choices_setting',\n                'description_setting',\n                'rules_setting',\n                'error_message_setting',\n                'css_class_setting',\n                'conditional_logic_field_setting',\n            ];\n        }\n\u00a0\n        public function is_value_submission_array() {\n            return true;\n        }\n\u00a0\n        public function get_field_input($form, $value = '', $entry = null) {\n            if ($this-&gt;is_form_editor()) {\n                return '';\n            }\n\u00a0\n            $id = (int) $this-&gt;id;\n            if ($this-&gt;is_entry_detail()) {\n                $table_value = maybe_unserialize($value);\n            } else {\n                $table_value = $this-&gt;translateValueArray($value);\n            }\n\u00a0\n            $table = '&lt;table class=\"delivery-table\"&gt;&lt;tbody&gt;&lt;tr&gt;';\n            $table .= '&lt;th&gt;'. __('Course', 'txtdomain'). '&lt;\/th&gt;';\n            foreach ($this-&gt;delivery_days as $day) {\n                $table .= '&lt;th&gt;'. $day. '&lt;\/th&gt;';\n            }\n            $table .= '&lt;\/tr&gt;';\n\u00a0\n            foreach ($this-&gt;choices as $course) {\n                $table .= '&lt;tr&gt;';\n                $table .= '&lt;td&gt;'. $course['text']. '&lt;\/td&gt;';\n                foreach ($this-&gt;delivery_days as $day) {\n                    $table .= '&lt;td&gt;&lt;input type=\"number\" size=\"1\" name=\"input_'. $id. '[]\" value=\"'. $table_value[$course['text']][$day]. '\" \/&gt;&lt;\/td&gt;';\n                }\n                $table .= '&lt;\/tr&gt;';\n            }\n\u00a0\n            $table .= '&lt;\/tbody&gt;&lt;\/table&gt;';\n\u00a0\n            return $table;\n        }\n\u00a0\n        private function translateValueArray($value) {\n            if (empty($value)) {\n                return [];\n            }\n            $table_value = [];\n            $counter = 0;\n            foreach ($this-&gt;choices as $course) {\n                foreach ($this-&gt;delivery_days as $day) {\n                    $table_value[$course['text']][$day] = $value[$counter++];\n                }\n            }\n            return $table_value;\n        }\n\u00a0\n        public function get_value_save_entry($value, $form, $input_name, $lead_id, $lead) {\n            if (empty($value)) {\n                $value = '';\n            } else {\n                $table_value = $this-&gt;translateValueArray($value);\n                $value = serialize($table_value);\n            }\n            return $value;\n        }\n\u00a0\n        private function prettyListOutput($value) {\n            $str = '&lt;ul&gt;';\n            foreach ($value as $course =&gt; $days) {\n                $week = '';\n                foreach ($days as $day =&gt; $delivery_number) {\n                    if (!empty($delivery_number)) {\n                        $week .= '&lt;li&gt;'. $day. ': '. $delivery_number. '&lt;\/li&gt;';\n                    }\n                }\n                \/\/ Only add week if there were any requests at all\n                if (!empty($week)) {\n                    $str .= '&lt;li&gt;&lt;h3&gt;'. $course. '&lt;\/h3&gt;&lt;ul class=\"days\"&gt;'. $week. '&lt;\/ul&gt;&lt;\/li&gt;';\n                }\n            }\n            $str .= '&lt;\/ul&gt;';\n            return $str;\n        }\n\u00a0\n        public function get_value_entry_list($value, $entry, $field_id, $columns, $form) {\n            return __('Enter details to see delivery details', 'txtdomain');\n        }\n\u00a0\n        public function get_value_entry_detail($value, $currency = '', $use_text = false, $format = 'html', $media = 'screen') {\n            $value = maybe_unserialize($value);     \n            if (empty($value)) {\n                return $value;\n            }\n            $str = $this-&gt;prettyListOutput($value);\n            return $str;\n        }\n\u00a0\n        public function get_value_merge_tag($value, $input_id, $entry, $form, $modifier, $raw_value, $url_encode, $esc_html, $format, $nl2br) {\n            return $this-&gt;prettyListOutput($value);\n        }\n\u00a0\n        public function is_value_submission_empty($form_id) {\n            $value = rgpost('input_'. $this-&gt;id);\n            foreach ($value as $input) {\n                if (strlen(trim($input)) &gt; 0) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n    GF_Fields::register(new FoodDelivery());\n}<\/code><\/pre>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un didacticiel montrant comment cr\u00e9er un type de champ Gravity Forms personnalis\u00e9 avanc\u00e9 avec plusieurs entr\u00e9es avec une gestion sp\u00e9ciale pour stocker et afficher les valeurs.<\/p>\n","protected":false},"author":1,"featured_media":153180,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[893,893,1110,801,801,811,811,841,841,862,862],"tags":[1167],"class_list":["post-234219","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-code-2","category-n-a","category-php-3","category-plugins-2","category-tutoriels","category-wordpress-3","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/234219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=234219"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/234219\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/153180"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=234219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=234219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=234219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}