{"id":233512,"date":"2023-02-15T17:35:00","date_gmt":"2023-02-15T14:35:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233512"},"modified":"2022-11-11T00:06:09","modified_gmt":"2022-11-10T21:06:09","slug":"esercitazione-creare-un-tipo-di-campo-moduli-di-gravita-personalizzati-avanzati-e-come-gestire-piu-valori-di-input","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/it\/esercitazione-creare-un-tipo-di-campo-moduli-di-gravita-personalizzati-avanzati-e-come-gestire-piu-valori-di-input\/","title":{"rendered":"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input"},"content":{"rendered":"\n<p>In questo tutorial ti mostrer\u00f2 come creare un tipo di campo Gravity Forms personalizzato avanzato. Il campo avr\u00e0 pi\u00f9 input e richieder\u00e0 una gestione speciale per memorizzare e visualizzare i valori inviati.<\/p>\n<h2>Cosa faremo<\/h2>\n<p>In questo esempio sto assumendo un esempio di proprietario di un sito Web WordPress che si occupa delle consegne di pranzo sul posto di lavoro. Il proprietario ha un modulo per le persone da compilare che tipo di pranzo vogliono e quanti per ogni giorno della settimana. Questo pu\u00f2 essere risolto come un metodo simile a una tabella per inserire un numero per qualsiasi corso in qualsiasi giorno in cui desiderano essere consegnati.<\/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=\"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input\" ><\/a><\/p>\n<p>I corsi sono modificabili nelle impostazioni del campo nell&#8217;editor di moduli e possono essere modificati in qualsiasi momento. E per ogni invio di modulo, il proprietario del sito Web ottiene una panoramica completa dei valori inviati:<\/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=\"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input\" ><\/a><\/p>\n<p>Ovviamente questo \u00e8 solo un esempio e probabilmente dovrai adattarlo al tuo caso. Ma con questo caso di esempio abbiamo la possibilit\u00e0 di imparare a gestire pi\u00f9 input in un singolo campo. Dovrebbe darti alcune idee su come gestire il tuo tipo di campo personalizzato.<\/p>\n<h2>Prima di iniziare a codificare<\/h2>\n<p>Prima di iniziare abbiamo bisogno di un posto dove aggiungere il nostro codice. Puoi aggiungerlo nel <code>functions.php<\/code>file del tuo tema o del tuo plug-in.<\/p>\n<p>Il metodo che ho scelto di utilizzare \u00e8 orientato agli oggetti, il che significa creare una classe che estenda la <code>GF_Field<\/code>classe di Gravity Forms. Ti consiglio di mettere la classe in un file separato nel tuo progetto. Dovresti anche verificare che il plug-in Gravity Forms esista prima di includere la tua classe per evitare il crash del tuo sito.<\/p>\n<p>Se sei interessato puoi dare un&#8217;occhiata alla <a href=\"https:\/\/docs.gravityforms.com\/gf_field\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">documentazione di Gravity Forms su GF_Field<\/a>. Troverai pi\u00f9 funzioni e variabili di cui potresti aver bisogno per il tuo tipo di campo.<\/p>\n<p>Estendendo la <code>GF_Field<\/code>classe possiamo semplicemente scegliere di sovrascrivere le funzioni che dobbiamo modificare. Per quanto riguarda le funzioni che non sovrascriviamo, Gravity Forms eseguir\u00e0 il valore predefinito definito all&#8217;interno di <code>GF_Field<\/code>. Nel tutorial di seguito esamineremo ogni funzione che dobbiamo sovrascrivere per il nostro campo personalizzato una per una. Senza ulteriori indugi, iniziamo!<\/p>\n<h2>Creazione di un tipo di campo personalizzato<\/h2>\n<p>Il primo passo \u00e8 definire una classe PHP personalizzata che estenda <code>GF_Field<\/code>. Assegna alla classe un nome univoco e assicurati che sia incluso nel tuo progetto. Dopo la definizione della classe eseguiamo la <code>register()<\/code>funzione static <code>GF_Field<\/code>passando un&#8217;istanza della nostra classe come parametro. Questo inizializza la nostra classe e registra il tipo di campo.<\/p>\n<p>L&#8217;unica variabile richiesta di cui hai bisogno all&#8217;interno della tua classe \u00e8 <code>$type<\/code>. La variabile di classe <code>$type<\/code>deve essere univoca ed \u00e8 un nome slug del tipo di campo. Nel mio esempio l&#8217;ho chiamato &#8216; <code>food_delivery<\/code>&#8216;.<\/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>Con questo piccolo pezzo di codice il nostro tipo di campo personalizzato dovrebbe essere aggiunto come scelta disponibile nell&#8217;editor Gravity Forms. Per impostazione predefinita appare alla fine della casella &quot;Campi standard&quot;. Poich\u00e9 non abbiamo ancora assegnato un nome corretto al nostro campo (questo \u00e8 il passaggio successivo), il pulsante \u00e8 etichettato come il valore di <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=\"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input\" ><\/a><\/p>\n<h2>Definizione del nome del campo<\/h2>\n<p>Il passo successivo \u00e8 facile; semplicemente dando al nostro campo un nome migliore. Per fare ci\u00f2 sovrascriviamo la funzione <code>get_form_editor_field_title()<\/code>. Tutto quello che dobbiamo fare \u00e8 restituire una stringa con il nome del campo.<\/p>\n<pre><code>public function get_form_editor_field_title() {\n    return esc_attr__('Food Delivery', 'txtdomain');\n}<\/code><\/pre>\n<p>Con questa funzione nella nostra classe il pulsante per aggiungere il campo viene aggiornato con un&#8217;etichetta molto migliore.<\/p>\n<h2>Modifica della categoria del campo<\/h2>\n<p>Questo passaggio \u00e8 facoltativo. Come impostazione predefinita, il nostro tipo di campo personalizzato appare nella casella &quot;Campi standard&quot;, ma possiamo cambiarlo. Supponiamo di volere che appaia invece all&#8217;interno della casella &quot;Campi avanzati&quot;.<\/p>\n<p>Per cambiare la categoria in cui vogliamo che appaia il campo, sovrascriviamo la funzione <code>get_form_editor_button()<\/code>. Dobbiamo restituire un array associativo con due elementi. Come valore per la chiave &#8216; <code>group<\/code>&#8216; fornisci il nome interno della categoria in cui desideri che appaia il pulsante. Le opzioni disponibili qui sono &#8216; <code>standard_fields<\/code>&#8216;, &#8216; <code>advanced_fields<\/code>&#8216;, &#8216; <code>post_fields<\/code>&#8216; o &#8216; <code>pricing_fields<\/code>&#8216;. (Puoi anche creare la tua categoria, ma non \u00e8 trattata qui). Il secondo elemento nell&#8217;array necessita della chiave &#8216; <code>text<\/code>&#8216; e per questo restituiamo semplicemente il nome del campo chiamando <code>get_form_editor_field_title()<\/code>. Questa \u00e8 la funzione che abbiamo appena creato sopra.<\/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>Ora il pulsante per aggiungere il nostro tipo di campo personalizzato viene spostato nella casella &quot;Campi avanzati&quot;.<\/p>\n<h2>Attivazione delle impostazioni in loco<\/h2>\n<p>Se hai provato ad aggiungere il tipo di campo in un modulo, potresti aver notato che non ci sono impostazioni. Non puoi nemmeno modificare l&#8217;etichetta. Il modo in cui funziona \u00e8 che tutti i tipi di impostazioni sono effettivamente presenti, sono semplicemente tutti nascosti con CSS di Gravity Forms. Dobbiamo definire individualmente quali impostazioni vogliamo abilitare e Gravity Forms mostrer\u00e0 quindi le impostazioni scelte per noi.<\/p>\n<p>Dobbiamo definire la funzione <code>get_form_editor_field_settings()<\/code>e restituire un array di tutte le impostazioni che non vogliamo nascondere per il nostro tipo di campo. Quali impostazioni vuoi aggiungere dipende interamente da te e dal tuo progetto. Tieni presente che il tuo campo dovrebbe supportare tutte le impostazioni che attivi, altrimenti non ha senso mostrare un&#8217;impostazione per esso.<\/p>\n<p>Ho creato una rapida panoramica dei nomi delle impostazioni di seguito. Questo \u00e8 tutt&#8217;altro che un elenco completo, perch\u00e9 ci sono molte impostazioni che sono praticamente utili solo per tipi di campo molto specifici. Ad esempio il formato del telefono, il formato data\/ora e un sacco di impostazioni relative ai campi Posta e Prezzi.<\/p>\n<h4>Scheda Generale<\/h4>\n<ul>\n<li>Etichetta campo:<code>label_setting<\/code><\/li>\n<li>Descrizione campo:<code>description_setting<\/code><\/li>\n<li>Scelte:<code>choices_setting<\/code><\/li>\n<li>Necessario:<code>rules_setting<\/code><\/li>\n<li>Nessun duplicato:<code>duplicate_setting<\/code><\/li>\n<li>Abilita colonne:<code>columns_setting<\/code><\/li>\n<li>Abilita la scelta &quot;seleziona tutto&quot;:<code>select_all_choices_setting<\/code><\/li>\n<li>Abilita la scelta &quot;altro&quot;:<code>other_choice_setting<\/code><\/li>\n<\/ul>\n<h4>Scheda Aspetto<\/h4>\n<ul>\n<li>Segnaposto:<code>placeholder_setting<\/code><\/li>\n<li>Visibilit\u00e0 dell&#8217;etichetta del campo e posizionamento della descrizione:<code>label_placement_setting<\/code><\/li>\n<li>Messaggio di convalida personalizzato:<code>error_message_setting<\/code><\/li>\n<li>Classe CSS personalizzata:<code>css_class_setting<\/code><\/li>\n<li>Dimensione del campo:<code>size_setting<\/code><\/li>\n<\/ul>\n<h4>Scheda Avanzate<\/h4>\n<ul>\n<li>Etichetta campo amministratore:<code>admin_label_setting<\/code><\/li>\n<li>Valore di default:<code>default_value_setting<\/code><\/li>\n<li>Abilita inserimento password:<code>password_field_setting<\/code><\/li>\n<li>Forza SSL:<code>force_ssl_field_setting<\/code><\/li>\n<li>Visibilit\u00e0:<code>visibility_setting<\/code><\/li>\n<li>Consenti il \u200b\u200briempimento dinamico del campo:<code>prepopulate_field_setting<\/code><\/li>\n<li>Abilita logica condizionale:<code>conditional_logic_field_setting<\/code><\/li>\n<li>Abilita la logica condizionale della pagina:<code>conditional_logic_page_setting<\/code><\/li>\n<\/ul>\n<p>Come per il nostro esempio, le pi\u00f9 importanti sono l&#8217;etichetta del campo, la descrizione, le scelte e se il campo \u00e8 richiesto o meno. Consentiamo anche le impostazioni per la classe CSS, il messaggio di convalida personalizzato e la logica condizionale.<\/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>Aggiorna l&#8217;editor di moduli e ora dovresti vedere tutte le impostazioni e le schede scelte apparire all&#8217;interno del nostro campo. Tutte le impostazioni vengono gestite e salvate automaticamente da Gravity Forms.<\/p>\n<p>Vai avanti e aggiungi alcuni elementi nell&#8217;elenco Scelte in modo da avere qualcosa con cui lavorare. Ecco cosa ho impostato come esempio:<\/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=\"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input\" ><\/a><\/p>\n<h2>Definizione di scelte predefinite personalizzate<\/h2>\n<p>Se sei abituato ad usare, ad esempio, pulsanti di opzione o caselle di controllo in Gravity Forms, probabilmente avrai notato che vengono proposti con scelte come &quot;Prima scelta&quot;, &quot;Seconda scelta&quot;, &quot;Terza scelta&quot;. Questo \u00e8 il comportamento predefinito di Gravity Forms se nessuna scelta \u00e8 stata salvata (prima) e si attiva solo su questi tipi di campo specifici. Ma per il nostro tipo di campo personalizzato, nessuna scelta verr\u00e0 popolata. Questo lo rende un po&#8217; ingombrante, perch\u00e9 non otterrai il pulsante &quot;+&quot; per aggiungere un&#8217;altra scelta. Dovresti usare il pulsante &quot;Aggiungi in blocco\/Scelte predefinite&quot;, aggiungere alcune scelte l\u00ec e, successivamente, avrai accesso ai pulsanti &quot;+&quot; per aggiungere scelte. Ma \u00e8 facile definire alcune scelte personalizzate: tutto ci\u00f2 che serve \u00e8 definire una variabile array di classe<code>public $choices<\/code>e Gravity Forms genereranno automaticamente scelte predefinite nel tuo campo quando lo aggiungi ai tuoi moduli.<\/p>\n<p>Nota: questa \u00e8 una variabile di classe, che puoi aggiungere nella parte superiore della classe, proprio sotto <code>public $type<\/code>. Ogni scelta deve essere un array, con la scelta come valore per la chiave &#8216; <code>text<\/code>&#8216;.<\/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>Tieni presente che se hai gi\u00e0 aggiunto il campo al modulo, non compiler\u00e0 retroattivamente le scelte. Questo diventa effettivo solo quando aggiungi un nuovo campo al modulo.<\/p>\n<p><strong>Nota<\/strong>: in Gravity Forms sembra essere possibile aggiungere anche chiavi &#8216; <code>value<\/code>&#8216; a ciascuna scelta. Ma non ho questo per funzionare: i valori diventeranno automaticamente gli stessi del testo scelto.<\/p>\n<h2>Definire il valore del campo come array<\/h2>\n<p>Il passaggio successivo \u00e8 piuttosto semplice, ma necessario. Come valori predefiniti per i campi in Gravity Forms sono stringhe. Abbiamo bisogno che il valore sia un array perch\u00e9 lavoriamo con pi\u00f9 input. Per fare ci\u00f2 definiamo la funzione <code>is_value_submission_array()<\/code>e restituiamo <code>true<\/code>.<\/p>\n<pre><code>public function is_value_submission_array() {\n    return true;\n}<\/code><\/pre>\n<p>Ci\u00f2 garantisce che possiamo lavorare correttamente con il valore inserito dei nostri input multipli.<\/p>\n<h2>Rendering dell&#8217;output del campo<\/h2>\n<p>Quando si tratta di rendere l&#8217;output del campo, ci sono un paio di cose di cui essere consapevoli.<\/p>\n<p>Prima di tutto \u00e8 necessario scegliere tra due funzioni; <code>get_field_input()<\/code>o <code>get_field_content()<\/code>. Nel primo metodo Gravity Forms rende automaticamente l&#8217;elemento dell&#8217;elenco di wrapping, l&#8217;etichetta, la descrizione e il messaggio di errore del contenitore per la convalida nel tuo campo e tu controlli solo l&#8217;output del campo interno. Con il secondo metodo non accade nulla di tutto ci\u00f2 e hai pi\u00f9 controllo sull&#8217;output del campo. Tuttavia \u00e8 necessario eseguire manualmente il rendering dell&#8217;etichetta, della descrizione e dei messaggi di errore. Il primo metodo, <code>get_field_input()<\/code>, \u00e8 perfetto per la maggior parte dei casi.<\/p>\n<p>La seconda cosa da tenere presente \u00e8 che la funzione di rendering per il campo interessa tre diverse posizioni. I tre sono il rendering dell&#8217;output del campo nel frontend, l&#8217;anteprima per il campo all&#8217;interno dell&#8217;editor di moduli e infine anche il campo durante la modifica di una voce. Fortunatamente Gravity Forms offre funzioni per determinare facilmente a quale vista ci troviamo. Di solito il campo viene visualizzato allo stesso modo in tutti e tre i casi. Ma poich\u00e9 il rendering di una tabella di grandi dimensioni con molti input diventa inutilmente goffo all&#8217;interno dell&#8217;editor di moduli, ho scelto di eseguire il rendering del campo in modo diverso all&#8217;interno dell&#8217;editor di moduli.<\/p>\n<p>E infine, dobbiamo assicurarci che qualsiasi input ottenga un <code>name<\/code>attributo appropriato in modo che Gravity Forms sia in grado di raccogliere il suo valore al momento dell&#8217;invio del modulo. Tutti gli input in Gravity Forms necessitano <code>name<\/code>di attributi che seguano questa regola: <code>name=\"input_{FIELD_ID}\"<\/code>(i campi a selezione multipla utilizzano un ID aggiuntivo, ma non dobbiamo preoccuparci di questo nel nostro caso). Abbiamo accesso all&#8217;ID del campo in quanto \u00e8 una variabile di classe (da <code>GF_Field<\/code>). Ma nel nostro caso abbiamo detto a Gravity Forms che il valore \u00e8 un array e non un valore singolare (passaggio precedente), quindi aggiungiamo parentesi dopo l&#8217;attributo name; <code>name=\"input_{FIELD_ID}[]\"<\/code>. Quindi, se il campo ha l&#8217;ID 4 all&#8217;interno di un modulo, l&#8217;attributo del nome dovrebbe essere &quot; <code>input_4[]<\/code>&quot;.<\/p>\n<p>Sto optando per l&#8217;utilizzo <code>get_field_input()<\/code>che viene fornito con tre parametri. Il primo parametro \u00e8 l&#8217;oggetto form, di cui non abbiamo davvero bisogno per il nostro esempio. Il secondo parametro \u00e8 il valore corrente. Questo pu\u00f2 essere il valore del campo da <code>$_POST<\/code>quando il modulo \u00e8 stato inviato, ma senza successo. Possiamo conservare i precedenti valori inviati. Oppure, se la funzione \u00e8 in esecuzione durante la modifica di una voce, il valore sar\u00e0 il valore memorizzato dall&#8217;invio. Tratteremo il valore pi\u00f9 da vicino in seguito. E il terzo parametro \u00e8 l&#8217;oggetto entry, di cui non avremo bisogno per il nostro esempio.<\/p>\n<p>Iniziamo a implementare <code>get_field_input()<\/code>che prevede il rendering finale come una stringa. Immediatamente decido di restituire una stringa vuota se siamo all&#8217;interno dell&#8217;editor di moduli, perch\u00e9 non voglio eseguire il rendering dell&#8217;intera tabella in questa vista. Possiamo utilizzare il metodo <code>$this-&gt;is_form_editor()<\/code>per verificare se siamo o meno all&#8217;interno della modifica del modulo. Puoi scegliere di saltare questo o eseguire il rendering di qualcos&#8217;altro se desideri un&#8217;anteprima del campo all&#8217;interno dell&#8217;editor di moduli.<\/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>Il passaggio successivo consiste nella creazione dell&#8217;HTML per una tabella che scorre su un array di giorni per generare le colonne e le righe per ogni elemento del corso. Ma poich\u00e9 abbiamo bisogno di accedere all&#8217;array di giorni (colonne della tabella) in pi\u00f9 posti, dovremmo definirlo come una variabile di classe, rendendolo accessibile da qualsiasi funzione al suo interno. Definisco una variabile di classe <code>$delivery_days<\/code>con una matrice dei giorni per cui voglio offrire la consegna.<\/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>Questo \u00e8 solo un esempio! Potresti voler recuperare l&#8217;array per le colonne da qualche altra parte che non \u00e8 hardcoded.<\/p>\n<p>Torniamo <code>get_field_input()<\/code>e costruiamo la nostra tabella con gli input. Per prima cosa eseguo il ciclo sulla variabile di classe e genero le intestazioni della tabella. Quindi ripeto le scelte immesse nell&#8217;impostazione del campo per Scelte. Questo \u00e8 accessibile dalla variabile di classe (da <code>GF_Field<\/code>) <code>$this-&gt;choices<\/code>. Per ogni scelta rendo un input con gli attributi del nome proprio. Abbiamo accesso all&#8217;ID del campo dalla <code>GF_Field<\/code>variabile di classe <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>Con questo codice in atto dovremmo ottenere una bella tabella renderizzata per il nostro tipo di campo nel frontend! Ovviamente l&#8217;HTML dipende interamente da te, questo \u00e8 solo un esempio di base.<\/p>\n<p><strong>Lasciamo questa funzione per ora, ma ci torneremo in seguito per gestire il valore inviato!<\/strong><\/p>\n<h2>Memorizzazione del valore correttamente<\/h2>\n<p>A partire da ora Gravity Forms salver\u00e0 il nostro campo come un array unidimensionale popolato con i valori inseriti e le stringhe vuote in cui l&#8217;input era vuoto. Non ci sono informazioni sul giorno o sulla scelta a cui appartiene il valore, a parte l&#8217;indice. Dobbiamo trasformare questo array unidimensionale in un array associativo multidimensionale in cui memorizziamo il giorno e l&#8217;etichetta di scelta. Possiamo quindi accedere facilmente al valore del numero memorizzato per es <code>$value['Ham sandwich']['Monday']<\/code>. Dopo questa trasformazione dell&#8217;array, dobbiamo anche serializzare l&#8217;array in modo che Gravity Forms possa memorizzare correttamente il valore nel database.<\/p>\n<p>Avremo bisogno di trasformare questo array di valori in pi\u00f9 posti, quindi definir\u00f2 una funzione separata per questo. La funzione accetta l&#8217;array unidimensionale e lo trasforma in un array multidimensionale con i valori memorizzati per i giorni e le scelte:<\/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>Ci\u00f2 memorizzer\u00e0 i nomi dei giorni e le scelte direttamente all&#8217;interno del valore del campo. In questo modo \u00e8 possibile modificare le scelte in un momento successivo senza interrompere le vecchie voci.<\/p>\n<p>Passiamo ora all&#8217;override della funzione che gestisce la memorizzazione del valore inviato; <code>get_value_save_entry()<\/code>. Viene fornito con cinque parametri, ma abbiamo solo bisogno del primo che \u00e8 il valore inviato. All&#8217;interno della funzione passiamo il valore nella nostra funzione personalizzata sopra, serializziamo il suo ritorno e infine restituiamo il nuovo valore.<\/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>A questo punto Gravity Forms memorizzer\u00e0 con successo i nostri valori proprio nel modo in cui li vogliamo! Tuttavia, il valore memorizzato \u00e8 ora un array serializzato che Gravity Forms far\u00e0 felicemente eco direttamente. Abbiamo bisogno di implementare funzioni per trasformarlo da un brutto array serializzato in un bel output ovunque ne abbiamo bisogno.<\/p>\n<h2>Visualizzazione del valore inviato<\/h2>\n<p>Ci sono tre posti in cui abbiamo bisogno per cambiare l&#8217;output del valore del nostro campo; l&#8217;elenco delle voci, guardando una singola voce e all&#8217;interno dei tag di unione di Gravity Forms. I tag di unione vengono utilizzati pi\u00f9 comunemente nelle notifiche e-mail. Ad esempio <code>{all_fields}<\/code>, c&#8217;\u00e8 un tag di unione che mostra i valori completi del modulo inviato nelle e-mail.<\/p>\n<p>Poich\u00e9 stiamo eseguendo il rendering dello stesso output in tre casi diversi, ha senso creare una funzione separata per esso. Ho definito una funzione personalizzata che accetta il valore; l&#8217;array multidimensionale non serializzato, come parametro. La funzione crea quindi un codice HTML che visualizza l&#8217;array in modo carino e restituisce la stringa. Ho optato per un <code>&lt;ul&gt;<\/code>elenco nidificato, ma puoi modificare l&#8217;output come preferisci.<\/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>Ottimo, iniziamo con il primo: l&#8217;elenco delle voci: <code>get_value_entry_list()<\/code>. Puoi scegliere di generare l&#8217;output completo qui, ma pu\u00f2 diventare piuttosto goffo e lungo per la visualizzazione elenco, quindi ho optato per restituire semplicemente una stringa fissa che spiega che l&#8217;utente deve entrare nei dettagli della voce per vedere la panoramica completa.<\/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>Questo ovviamente dipende interamente da te, potresti optare per la visualizzazione solo del primo x numero di caratteri, ad esempio.<\/p>\n<p>La seconda funzione \u00e8 quella che interessa la visualizzazione di una singola voce: <code>get_value_entry_detail()<\/code>:<\/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>Deserializziamo semplicemente l&#8217;array con la funzione di WordPress <code>[maybe_unserialize](https:\/\/developer.wordpress.org\/reference\/functions\/maybe_unserialize\/)()<\/code>e restituiamo l&#8217;output della stringa dalla nostra funzione personalizzata.<\/p>\n<p>La funzione finale influisce sui tag di unione e assicura che il valore del nostro campo appaia buono anche all&#8217;interno delle e-mail: <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>Nota che non avremo bisogno di annullare la serializzazione del valore all&#8217;interno di questa funzione.<\/p>\n<p>Con queste tre funzioni in atto, tutti i valori inviati dovrebbero avere un bell&#8217;aspetto ovunque! Ad esempio durante la visualizzazione di una voce inviata:<\/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=\"Esercitazione: creare un tipo di campo Moduli di gravit\u00e0 personalizzati avanzati e come gestire pi\u00f9 valori di input\" ><\/a><\/p>\n<p>Tuttavia manca una cosa importante! A questo punto i nostri input non mantengono i valori precedentemente inviati e questo \u00e8 piuttosto negativo.<\/p>\n<h2>Fai in modo che i nostri input mantengano il valore precedentemente inviato<\/h2>\n<p>Ci sono principalmente due casi in cui dobbiamo assicurarci che gli input mantengano i valori precedentemente inviati. Il primo caso \u00e8 quando l&#8217;invio di un modulo non \u00e8 riuscito (ad esempio l&#8217;utente ha dimenticato un campo obbligatorio). In questo momento tutti i nostri input perdono tutti i valori immessi in precedenza e l&#8217;utente deve reinserire tutti i valori. In secondo luogo, quando il proprietario del sito modifica una voce, gli input non vengono popolati con i valori inviati dall&#8217;invio, il che rende praticamente impossibile modificare i valori correttamente.<\/p>\n<p>Per risolvere questo problema torniamo alla funzione <code>get_field_input()<\/code>. Il secondo parametro di questa funzione \u00e8 il valore. Ma ricorda che questa funzione influisce sia sul rendering del frontend che sulla modifica della voce. Questo \u00e8 importante perch\u00e9 il valore memorizzato \u00e8 diverso in questi due casi. Se siamo al frontend e gestiamo l&#8217;invio del modulo, il valore \u00e8 nel formato dell&#8217;array unidimensionale menzionato in precedenza. E se stiamo modificando una voce, il valore \u00e8 nel formato di un array multidimensionale serializzato. Quindi dobbiamo tradurre correttamente il valore fornito <code>get_field_input()<\/code>per accedere facilmente ai valori effettivi.<\/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>Nel codice sopra, prima di iniziare a creare l&#8217;HTML per l&#8217;output del campo, creiamo una variabile <code>$table_value<\/code>che contiene il valore tradotto correttamente. Usiamo <code>GF_Field<\/code>la funzione di &#8216; <code>is_entry_detail()<\/code>per verificare se stiamo modificando o meno una voce. E poi per i nostri input \u00e8 facile accedere ai valori corretti e impostarli come <code>value<\/code>attributi degli input:<\/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>Con quanto sopra aggiornato <code>get_field_input()<\/code>tutti i nostri input personalizzati dovrebbero sempre essere popolati con il valore precedente; non importa se sta modificando una voce o riprovando a inviare un modulo.<\/p>\n<p>A questo punto tutto ci\u00f2 che riguarda il rendering e la memorizzazione dei nostri valori \u00e8 fatto e funziona completamente. Ma c&#8217;\u00e8 un&#8217;altra cosa che dobbiamo assolutamente sistemare.<\/p>\n<h2>Effettua la convalida &quot;richiesta&quot; del nostro pass sul campo<\/h2>\n<p>Gravity Forms ha controlli per vedere se il valore di un campo \u00e8 vuoto o meno. Questo \u00e8 spesso necessario quando il campo \u00e8 impostato come richiesto. Quando un campo \u00e8 obbligatorio non puoi inviare il modulo se \u00e8 vuoto, giusto? Il problema per noi \u00e8 che abbiamo pi\u00f9 input e vogliamo che alcuni di essi siano vuoti. Questo diventa un problema se il nostro campo \u00e8 impostato su obbligatorio. Gravity Forms sfortunatamente interpreta &quot;\u00e8 vuoto questo&quot; in modo errato e richiede che tutti gli input siano compilati. Quindi dobbiamo aggiungere una regola che dice che se almeno uno dei nostri molti input \u00e8 compilato, il valore totale del campo non \u00e8 vuoto.<\/p>\n<p>L&#8217;ultima funzione che dobbiamo sovrascrivere nella nostra classe \u00e8 <code>is_value_submission_empty()<\/code>. Otteniamo solo l&#8217;ID del modulo come parametro per questa funzione, quindi \u00e8 necessario estrarre il valore del campo utilizzando la funzione Gravity Forms per recuperarlo <code>$_POST<\/code>dall&#8217;array: <code>rgpost('input_&lt;FIELD ID&gt;')<\/code>. Il ritorno dovrebbe essere l&#8217;array unidimensionale che abbiamo visto prima. Tutto quello che dobbiamo fare \u00e8 scorrere l&#8217;array e restituire <code>false<\/code>se troviamo un valore da qualche parte. Altrimenti ritorniamo <code>true<\/code>in quanto il valore del campo \u00e8 effettivamente completamente vuoto.<\/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>Con la funzione di cui sopra in atto, il nostro campo non fallir\u00e0 l&#8217;invio se \u00e8 impostato su obbligatorio e almeno un input \u00e8 compilato.<\/p>\n<h2>Conclusione e codice finale<\/h2>\n<p>Questo tutorial ti ha mostrato in dettaglio come creare il tuo tipo di campo avanzato personalizzato per Gravity Forms. Anche se il tuo progetto \u00e8 diverso dal mio esempio, spero che tu abbia alcuni suggerimenti e a-ha lungo la strada. Trovo che la documentazione di Gravity Forms sia piuttosto carente in alcuni casi, e questo \u00e8 il risultato di molti tentativi ed errori! Comunque, spero che questo ti sia stato di qualche utilit\u00e0!<\/p>\n<p>Per riferimento, ecco il codice completo nella sua interezza:<\/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\">Fonte di registrazione:  <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 tutorial che mostra come creare un tipo di campo Gravity Forms personalizzato avanzato con pi\u00f9 input con una gestione speciale per memorizzare e visualizzare i valori.<\/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":[896,896,1110,804,804,814,814,844,844,865,865],"tags":[1168],"class_list":{"0":"post-233512","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","6":"hentry","7":"category-codice","9":"category-n-a","10":"category-php-6","12":"category-plugin-2","14":"category-tutorial","16":"category-wordpress-6","18":"tag-affiai-it"},"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/233512","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/comments?post=233512"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/233512\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media\/153180"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media?parent=233512"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/categories?post=233512"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/tags?post=233512"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}