{"id":233459,"date":"2023-02-15T17:24:00","date_gmt":"2023-02-15T14:24:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233459"},"modified":"2022-11-10T23:48:08","modified_gmt":"2022-11-10T20:48:08","slug":"handledning-skapa-en-avancerad-faelttyp-foer-anpassade-gravitationsformulaer-och-hur-man-hanterar-flera-inmatningsvaerden","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/sv\/handledning-skapa-en-avancerad-faelttyp-foer-anpassade-gravitationsformulaer-och-hur-man-hanterar-flera-inmatningsvaerden\/","title":{"rendered":"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden"},"content":{"rendered":"\n<p>I den h\u00e4r handledningen visar jag dig hur du skapar en avancerad anpassad Gravity Forms-f\u00e4lttyp. F\u00e4ltet kommer att ha flera inmatningar och kommer att beh\u00f6va speciell hantering f\u00f6r att lagra och visa de inskickade v\u00e4rdena.<\/p>\n<h2>Vad vi ska g\u00f6ra<\/h2>\n<p>I det h\u00e4r exemplet utg\u00e5r jag fr\u00e5n ett exempel p\u00e5 en WordPress-webbplats\u00e4gare som sysslar med lunchleveranser p\u00e5 en arbetsplats. \u00c4garen har ett formul\u00e4r d\u00e4r folk kan fylla i vilken typ av lunch de vill ha och hur m\u00e5nga f\u00f6r varje dag i veckan. Detta kan l\u00f6sas som en tabellliknande metod f\u00f6r att mata in ett nummer f\u00f6r vilken kurs som helst p\u00e5 vilken dag de vill ha leverans.<\/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=\"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden\" ><\/a><\/p>\n<p>Kurserna \u00e4r redigerbara i f\u00e4ltets inst\u00e4llningar i formul\u00e4rredigeraren och kan \u00e4ndras n\u00e4r som helst. Och f\u00f6r varje formul\u00e4rinl\u00e4mning f\u00e5r webbplats\u00e4garen en fullst\u00e4ndig \u00f6versikt \u00f6ver de inl\u00e4mnade v\u00e4rdena:<\/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=\"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden\" ><\/a><\/p>\n<p>Uppenbarligen \u00e4r detta bara ett exempel och du m\u00e5ste f\u00f6rmodligen anpassa detta till ditt fall. Men med det h\u00e4r exemplet f\u00e5r vi en chans att l\u00e4ra oss hur man hanterar flera input i ett enda f\u00e4lt. Det borde ge dig n\u00e5gra id\u00e9er om hur du hanterar din egen anpassade f\u00e4lttyp.<\/p>\n<h2>Innan du b\u00f6rjar koda<\/h2>\n<p>Innan vi b\u00f6rjar beh\u00f6ver vi en plats f\u00f6r att l\u00e4gga till v\u00e5r kod. Du kan l\u00e4gga till detta i ditt tema <code>functions.php<\/code>eller din plugin-fil.<\/p>\n<p>Metoden jag har valt att g\u00e5 efter \u00e4r objektorienterad, vilket inneb\u00e4r att skapa en klass som ut\u00f6kar Gravity Forms <code>GF_Field<\/code>klass. Jag rekommenderar att du l\u00e4gger klassen i en separat fil i ditt projekt. Du b\u00f6r ocks\u00e5 kontrollera att Gravity Forms plugin finns innan du inkluderar din klass f\u00f6r att f\u00f6rhindra att din webbplats kraschar.<\/p>\n<p>Om du \u00e4r intresserad kan du ta en titt p\u00e5 <a href=\"https:\/\/docs.gravityforms.com\/gf_field\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Gravity Forms dokumentation p\u00e5 GF_Field<\/a>. Du hittar fler funktioner och variabler som du kan beh\u00f6va f\u00f6r din f\u00e4lttyp.<\/p>\n<p>Genom att ut\u00f6ka <code>GF_Field<\/code>klassen kan vi helt enkelt v\u00e4lja att \u00e5sidos\u00e4tta de funktioner vi beh\u00f6ver \u00e4ndra. N\u00e4r det g\u00e4ller de funktioner vi inte \u00e5sidos\u00e4tter, kommer Gravity Forms att k\u00f6ra standarden som definieras inuti <code>GF_Field<\/code>. I handledningen nedan g\u00e5r vi igenom varje funktion vi beh\u00f6ver \u00e5sidos\u00e4tta f\u00f6r v\u00e5rt anpassade f\u00e4lt en efter en. Utan vidare, l\u00e5t oss b\u00f6rja!<\/p>\n<h2>Skapa en anpassad f\u00e4lttyp<\/h2>\n<p>Det f\u00f6rsta steget \u00e4r att definiera en anpassad PHP-klass som ut\u00f6kar <code>GF_Field<\/code>. Ge klassen ett unikt namn och se till att det ing\u00e5r i ditt projekt. Efter klassdefinitionen k\u00f6r vi den <code>register()<\/code>statiska funktionen <code>GF_Field<\/code>genom att skicka en instans av v\u00e5r klass som parameter. Detta initierar v\u00e5r klass och registrerar f\u00e4lttypen.<\/p>\n<p>Den enda obligatoriska variabeln du beh\u00f6ver i din klass \u00e4r <code>$type<\/code>. Klassvariabeln <code>$type<\/code>m\u00e5ste vara unik och \u00e4r ett snigelnamn f\u00f6r din f\u00e4lttyp. I mitt exempel har jag d\u00f6pt det till &#8217; <code>food_delivery<\/code>&#8217;.<\/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>Med denna lilla kodbit b\u00f6r v\u00e5r anpassade f\u00e4lttyp l\u00e4ggas till som ett tillg\u00e4ngligt val i Gravity Forms-redigeraren. Som standard visas den i slutet av &quot;Standardf\u00e4lt&quot;-rutan. Eftersom vi inte har gett v\u00e5rt f\u00e4lt ett r\u00e4tt namn \u00e4n (det \u00e4r n\u00e4sta steg), \u00e4r knappen m\u00e4rkt som v\u00e4rdet p\u00e5 <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=\"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden\" ><\/a><\/p>\n<h2>Definiera f\u00e4ltets namn<\/h2>\n<p>N\u00e4sta steg \u00e4r l\u00e4tt; helt enkelt ge v\u00e5rt omr\u00e5de ett b\u00e4ttre namn. F\u00f6r att g\u00f6ra det \u00e5sidos\u00e4tter vi funktionen <code>get_form_editor_field_title()<\/code>. Allt vi beh\u00f6ver g\u00f6ra \u00e4r att returnera en str\u00e4ng med f\u00e4ltets namn.<\/p>\n<pre><code>public function get_form_editor_field_title() {\n    return esc_attr__('Food Delivery', 'txtdomain');\n}<\/code><\/pre>\n<p>Med denna funktion i v\u00e5r klass uppdateras knappen f\u00f6r att l\u00e4gga till f\u00e4ltet med en mycket b\u00e4ttre etikett.<\/p>\n<h2>\u00c4ndra f\u00e4ltkategori<\/h2>\n<p>Detta steg \u00e4r valfritt. Som standard visas v\u00e5r anpassade f\u00e4lttyp i rutan &quot;Standardf\u00e4lt&quot;, men vi kan \u00e4ndra det. L\u00e5t oss anta att vi vill att det ska visas i rutan &quot;Avancerade f\u00e4lt&quot; ist\u00e4llet.<\/p>\n<p>F\u00f6r att \u00e4ndra kategorin vi vill att f\u00e4ltet ska visas i \u00e5sidos\u00e4tter vi funktionen <code>get_form_editor_button()<\/code>. Vi m\u00e5ste returnera en associativ array med tv\u00e5 element. Som v\u00e4rde till nyckeln &#8217; <code>group<\/code>&#8217; anger du det interna namnet p\u00e5 kategorin du vill att knappen ska visas i. Tillg\u00e4ngliga alternativ h\u00e4r \u00e4r &#8217; <code>standard_fields<\/code>&#8217;, &#8217; <code>advanced_fields<\/code>&#8217;, &#8217; <code>post_fields<\/code>&#8217; eller &#8217; <code>pricing_fields<\/code>&#8217;. (Du kan ocks\u00e5 skapa din egen kategori, men det tas inte upp h\u00e4r). Det andra elementet i arrayen beh\u00f6ver nyckeln &#8217; <code>text<\/code>&#8217; och f\u00f6r det returnerar vi helt enkelt f\u00e4ltets namn genom att anropa <code>get_form_editor_field_title()<\/code>. Det h\u00e4r \u00e4r funktionen vi just skapat ovan.<\/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>Nu flyttas knappen f\u00f6r att l\u00e4gga till v\u00e5r anpassade f\u00e4lttyp till rutan &quot;Avancerade f\u00e4lt&quot;.<\/p>\n<h2>Aktiverar f\u00e4ltinst\u00e4llningar<\/h2>\n<p>Om du har f\u00f6rs\u00f6kt l\u00e4gga till f\u00e4lttypen i ett formul\u00e4r kanske du har m\u00e4rkt att det inte finns n\u00e5gra inst\u00e4llningar alls. Du kan inte ens redigera etiketten. S\u00e4ttet detta fungerar \u00e4r att alla typer av inst\u00e4llningar faktiskt finns d\u00e4r, de \u00e4r helt enkelt alla dolda med CSS av Gravity Forms. Vi m\u00e5ste definiera individuellt vilka inst\u00e4llningar vi vill aktivera, och Gravity Forms visar sedan de valda inst\u00e4llningarna \u00e5t oss.<\/p>\n<p>Vi m\u00e5ste definiera funktionen <code>get_form_editor_field_settings()<\/code>och returnera en upps\u00e4ttning av alla inst\u00e4llningar som vi inte vill d\u00f6lja f\u00f6r v\u00e5r f\u00e4lttyp. Vilka inst\u00e4llningar du vill l\u00e4gga till \u00e4r helt upp till dig och ditt projekt. T\u00e4nk p\u00e5 att ditt f\u00e4lt ska st\u00f6dja vilka inst\u00e4llningar du \u00e4n aktiverar, annars \u00e4r det meningsl\u00f6st att visa en inst\u00e4llning f\u00f6r det.<\/p>\n<p>Jag har skapat en snabb \u00f6versikt \u00f6ver inst\u00e4llningarnas namn nedan. Detta \u00e4r l\u00e5ngt ifr\u00e5n en komplett lista \u2013 eftersom det finns m\u00e5nga inst\u00e4llningar som i stort sett bara \u00e4r anv\u00e4ndbara f\u00f6r mycket specifika f\u00e4lttyper. Till exempel telefonformat, datum\/tidsformat och en hel massa inst\u00e4llningar som \u00e4r relaterade till Postf\u00e4lt och Prisf\u00e4lt.<\/p>\n<h4>Fliken Allm\u00e4nt<\/h4>\n<ul>\n<li>F\u00e4ltetikett:<code>label_setting<\/code><\/li>\n<li>F\u00e4ltbeskrivning:<code>description_setting<\/code><\/li>\n<li>Alternativ:<code>choices_setting<\/code><\/li>\n<li>N\u00f6dv\u00e4ndig:<code>rules_setting<\/code><\/li>\n<li>Inga dubbletter:<code>duplicate_setting<\/code><\/li>\n<li>Aktivera kolumner:<code>columns_setting<\/code><\/li>\n<li>Aktivera &quot;v\u00e4lj alla&quot; val:<code>select_all_choices_setting<\/code><\/li>\n<li>Aktivera &quot;annat&quot; val:<code>other_choice_setting<\/code><\/li>\n<\/ul>\n<h4>Fliken Utseende<\/h4>\n<ul>\n<li>Platsh\u00e5llare:<code>placeholder_setting<\/code><\/li>\n<li>F\u00e4ltetikettssynlighet och beskrivningsplacering:<code>label_placement_setting<\/code><\/li>\n<li>Anpassat valideringsmeddelande:<code>error_message_setting<\/code><\/li>\n<li>Anpassad CSS-klass:<code>css_class_setting<\/code><\/li>\n<li>F\u00e4ltstorlek:<code>size_setting<\/code><\/li>\n<\/ul>\n<h4>Fliken Avancerat<\/h4>\n<ul>\n<li>Admin f\u00e4ltetikett:<code>admin_label_setting<\/code><\/li>\n<li>Standardv\u00e4rde:<code>default_value_setting<\/code><\/li>\n<li>Aktivera l\u00f6senordsinmatning:<code>password_field_setting<\/code><\/li>\n<li>Tvinga SSL:<code>force_ssl_field_setting<\/code><\/li>\n<li>Synlighet:<code>visibility_setting<\/code><\/li>\n<li>Till\u00e5t att f\u00e4lt fylls i dynamiskt:<code>prepopulate_field_setting<\/code><\/li>\n<li>Aktivera villkorlig logik:<code>conditional_logic_field_setting<\/code><\/li>\n<li>Aktivera sidvillkorlig logik:<code>conditional_logic_page_setting<\/code><\/li>\n<\/ul>\n<p>N\u00e4r det g\u00e4ller v\u00e5rt exempel \u00e4r de viktigaste f\u00e4ltets etikett, beskrivning, val och om f\u00e4ltet \u00e4r obligatoriskt eller inte. Vi till\u00e5ter ocks\u00e5 inst\u00e4llningar f\u00f6r CSS-klass, anpassat valideringsmeddelande och villkorlig logik.<\/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>Uppdatera formul\u00e4rredigeraren och du b\u00f6r nu se alla valda inst\u00e4llningar och flikar visas i v\u00e5rt f\u00e4lt. Alla inst\u00e4llningar hanteras och sparas automatiskt av Gravity Forms.<\/p>\n<p>Vars\u00e5god och l\u00e4gg till n\u00e5gra objekt i listan Val s\u00e5 att vi har n\u00e5got att arbeta med. H\u00e4r \u00e4r vad jag har st\u00e4llt in som exempel:<\/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=\"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden\" ><\/a><\/p>\n<h2>Definiera anpassade standardval<\/h2>\n<p>Om du \u00e4r van vid att anv\u00e4nda t.ex. radioknappar eller kryssrutor i Gravity Forms, har du f\u00f6rmodligen m\u00e4rkt att de kommer med val som &quot;F\u00f6rsta val&quot;, &quot;Andra val&quot;, &quot;Tredje val&quot;. Detta \u00e4r standardbeteende fr\u00e5n Gravity Forms om inga val har sparats (f\u00f6rut) och detta utl\u00f6ses endast p\u00e5 dessa specifika f\u00e4lttyper. Men f\u00f6r v\u00e5r anpassade f\u00e4lttyp kommer inga val att fyllas i. Detta g\u00f6r det lite kr\u00e5ngligt, eftersom du inte kommer att f\u00e5 &quot;+&quot;-knappen f\u00f6r att l\u00e4gga till ett annat val. Du m\u00e5ste anv\u00e4nda knappen &quot;L\u00e4gg till\/f\u00f6rdefinierade val i bulk&quot;, l\u00e4gga till n\u00e5gra val d\u00e4r, och efter det f\u00e5r du tillg\u00e5ng till &quot;+&quot;-knappar f\u00f6r att l\u00e4gga till val. Men det \u00e4r l\u00e4tt att definiera n\u00e5gra anpassade val \u2013 allt du beh\u00f6ver \u00e4r att definiera en klassmatrisvariabel<code>public $choices<\/code>och Gravity Forms genererar automatiskt f\u00f6rdefinierade val i ditt f\u00e4lt n\u00e4r du l\u00e4gger till det i dina formul\u00e4r.<\/p>\n<p>Obs! Detta \u00e4r en klassvariabel som du kan l\u00e4gga till h\u00f6gst upp i klassen, precis nedanf\u00f6r <code>public $type<\/code>. Varje val m\u00e5ste vara en array, med valet som v\u00e4rde till nyckeln &#8217; <code>text<\/code>&#8217;.<\/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>T\u00e4nk p\u00e5 att om du redan har lagt till f\u00e4ltet i formul\u00e4ret kommer det inte att fylla i valen retroaktivt. Detta tr\u00e4der bara i kraft n\u00e4r du l\u00e4gger till ett nytt f\u00e4lt i formul\u00e4ret.<\/p>\n<p><strong>Notera<\/strong>: I Gravity Forms verkar det vara m\u00f6jligt att ocks\u00e5 l\u00e4gga till nycklar &#8217; <code>value<\/code>&#8217; till varje val. Men jag har inte f\u00e5tt detta att fungera \u2013 v\u00e4rdena blir automatiskt desamma som valtexten.<\/p>\n<h2>Definiera f\u00e4ltets v\u00e4rde som array<\/h2>\n<p>N\u00e4sta steg \u00e4r ganska enkelt, men n\u00f6dv\u00e4ndigt. Som standardv\u00e4rden f\u00f6r f\u00e4lt i Gravity Forms \u00e4r str\u00e4ngar. Vi beh\u00f6ver v\u00e4rdet vara en array eftersom vi arbetar med flera ing\u00e5ngar. F\u00f6r att g\u00f6ra detta definierar vi funktionen <code>is_value_submission_array()<\/code>och returnerar <code>true<\/code>.<\/p>\n<pre><code>public function is_value_submission_array() {\n    return true;\n}<\/code><\/pre>\n<p>Detta s\u00e4kerst\u00e4ller att vi kan arbeta korrekt med det angivna v\u00e4rdet av v\u00e5ra flera ing\u00e5ngar.<\/p>\n<h2>\u00c5terge f\u00e4ltutdata<\/h2>\n<p>N\u00e4r det g\u00e4ller att rendera f\u00e4ltets produktion finns det ett par saker att vara medveten om.<\/p>\n<p>F\u00f6rst och fr\u00e4mst \u00e4r att du m\u00e5ste v\u00e4lja mellan tv\u00e5 funktioner; <code>get_field_input()<\/code>eller <code>get_field_content()<\/code>. I den f\u00f6rsta metoden \u00e5terger Gravity Forms automatiskt omslagslistelementet, etiketten, beskrivningen och beh\u00e5llaren f\u00f6r valideringsfelmeddelande till ditt f\u00e4lt och du kontrollerar bara det inre f\u00e4ltets utdata. Med den andra metoden h\u00e4nder inget av detta och du har mer kontroll \u00f6ver f\u00e4ltets produktion. Du m\u00e5ste dock rendera etiketten, beskrivningen och felmeddelandena manuellt. Den f\u00f6rsta metoden, <code>get_field_input()<\/code>, \u00e4r helt ok i de flesta fall.<\/p>\n<p>Det andra man b\u00f6r vara medveten om \u00e4r att renderingsfunktionen f\u00f6r f\u00e4ltet p\u00e5verkar tre olika platser. De tre \u00e4r renderingen av f\u00e4ltets utdata i frontend, f\u00f6rhandsgranskningen av f\u00e4ltet i formul\u00e4rredigeraren och slutligen \u00e4ven f\u00e4ltet n\u00e4r du redigerar en post. Lyckligtvis erbjuder Gravity Forms funktioner f\u00f6r att enkelt avg\u00f6ra vilken vy vi befinner oss p\u00e5. Vanligtvis skulle du \u00e5terge f\u00e4ltet p\u00e5 samma s\u00e4tt i alla tre fallen. Men eftersom det blir on\u00f6digt klumpigt att rendera en stor tabell med m\u00e5nga ing\u00e5ngar i formul\u00e4rredigeraren, har jag valt att rendera f\u00e4ltet annorlunda i formul\u00e4rredigeraren.<\/p>\n<p>Och slutligen m\u00e5ste vi se till att alla inmatningar f\u00e5r ett korrekt <code>name<\/code>attribut s\u00e5 att Gravity Forms kan samla in sitt v\u00e4rde n\u00e4r formul\u00e4ret skickas in. Alla indata i Gravity Forms beh\u00f6ver <code>name<\/code>attribut som f\u00f6ljer denna regel: <code>name=\"input_{FIELD_ID}\"<\/code>(flervalsf\u00e4lt anv\u00e4nder ett extra ID, men vi beh\u00f6ver inte bry oss om det f\u00f6r v\u00e5rt fall). Vi har tillg\u00e5ng till f\u00e4lt-ID eftersom det \u00e4r en klassvariabel (fr\u00e5n <code>GF_Field<\/code>). Men i v\u00e5rt fall har vi sagt till Gravity Forms att v\u00e4rdet \u00e4r en array och inte ett singularv\u00e4rde (f\u00f6reg\u00e5ende steg), s\u00e5 vi l\u00e4gger till parenteser efter namnattributet; <code>name=\"input_{FIELD_ID}[]\"<\/code>. S\u00e5 om f\u00e4ltet har ID 4 i ett formul\u00e4r, b\u00f6r namnattributet vara &quot; <code>input_4[]<\/code>&quot;.<\/p>\n<p>Jag v\u00e4ljer att anv\u00e4nda <code>get_field_input()<\/code>som kommer med tre parametrar. Den f\u00f6rsta parametern \u00e4r formobjektet, som vi egentligen inte beh\u00f6ver f\u00f6r v\u00e5rt exempel. Den andra parametern \u00e4r det aktuella v\u00e4rdet. Detta kan antingen vara f\u00e4ltets v\u00e4rde fr\u00e5n <code>$_POST<\/code>n\u00e4r formul\u00e4ret f\u00f6rs\u00f6kte skickas in, men misslyckades. Vi kan beh\u00e5lla de tidigare inl\u00e4mnade v\u00e4rdena. Eller om funktionen k\u00f6rs f\u00f6r att redigera en post, kommer v\u00e4rdet att vara det lagrade v\u00e4rdet fr\u00e5n inl\u00e4mningen. Vi kommer att hantera v\u00e4rdet n\u00e4rmare senare. Och den tredje parametern \u00e4r entry-objektet, som vi inte heller beh\u00f6ver f\u00f6r v\u00e5rt exempel.<\/p>\n<p>L\u00e5t oss b\u00f6rja implementera <code>get_field_input()<\/code>som f\u00f6rv\u00e4ntar sig den slutliga renderingen som en str\u00e4ng. Jag best\u00e4mmer mig direkt f\u00f6r att returnera en tom str\u00e4ng om vi \u00e4r inne i formul\u00e4rredigeraren \u2013 eftersom jag inte vill rendera hela tabellen i den h\u00e4r vyn. Vi kan anv\u00e4nda metoden <code>$this-&gt;is_form_editor()<\/code>f\u00f6r att kontrollera om vi \u00e4r inne i formul\u00e4rredigering eller inte. Du kan v\u00e4lja att hoppa \u00f6ver detta eller rendera n\u00e5got annat om du vill ha en f\u00f6rhandsgranskning av f\u00e4ltet i formul\u00e4rredigeraren.<\/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>N\u00e4sta steg \u00e4r att bygga HTML-koden f\u00f6r en tabell som l\u00f6per \u00f6ver en rad dagar f\u00f6r att generera kolumnerna och raderna f\u00f6r varje kursobjekt. Men eftersom vi beh\u00f6ver tillg\u00e5ng till arrayen av dagar (tabellkolumner) flera platser, b\u00f6r vi definiera den som en klassvariabel, vilket g\u00f6r den tillg\u00e4nglig fr\u00e5n alla funktioner i den. Jag definierar en klassvariabel <code>$delivery_days<\/code>med en array av de dagar jag vill erbjuda leverans f\u00f6r.<\/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>Detta \u00e4r bara ett exempel! Du kanske vill h\u00e4mta arrayen f\u00f6r kolumnerna fr\u00e5n n\u00e5gon annanstans som inte \u00e4r h\u00e5rdkodad.<\/p>\n<p>L\u00e5t oss g\u00e5 tillbaka till <code>get_field_input()<\/code>och bygga upp v\u00e5r tabell med input. F\u00f6rst g\u00e5r jag \u00f6ver klassvariabeln och genererar tabellrubrikerna. Sedan loopar jag \u00f6ver de val som angetts i f\u00e4ltinst\u00e4llningen f\u00f6r Val. Detta \u00e4r tillg\u00e4ngligt fr\u00e5n klassvariabeln (fr\u00e5n <code>GF_Field<\/code>) <code>$this-&gt;choices<\/code>. F\u00f6r varje val g\u00f6r jag en indata med attributen f\u00f6r egennamn. Vi har tillg\u00e5ng till f\u00e4ltets ID fr\u00e5n <code>GF_Field<\/code>klassvariabeln <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>Med denna kod p\u00e5 plats borde vi f\u00e5 en snygg tabell renderad f\u00f6r v\u00e5r f\u00e4lttyp i frontend! Uppenbarligen \u00e4r HTML helt upp till dig, detta \u00e4r bara ett grundl\u00e4ggande exempel.<\/p>\n<p><strong>Vi l\u00e4mnar denna funktion tills vidare, men vi \u00e5terkommer till den senare f\u00f6r att hantera det inl\u00e4mnade v\u00e4rdet!<\/strong><\/p>\n<h2>Lagra v\u00e4rdet p\u00e5 r\u00e4tt s\u00e4tt<\/h2>\n<p>Fr\u00e5n och med nu kommer Gravity Forms att spara v\u00e5rt f\u00e4lt som en endimensionell array fylld med de inmatade v\u00e4rdena och tomma str\u00e4ngar d\u00e4r inmatningen var tom. Det finns ingen information om vilken dag eller val v\u00e4rdet tillh\u00f6r, f\u00f6rutom indexet. Vi beh\u00f6ver f\u00f6rvandla denna endimensionella array till en multidimensionell associativ array d\u00e4r vi lagrar dagen och valetiketten. Vi kan d\u00e5 enkelt komma \u00e5t det lagrade talv\u00e4rdet f\u00f6r <code>$value['Ham sandwich']['Monday']<\/code>t.ex. Efter denna arraytransformation beh\u00f6ver vi ocks\u00e5 serialisera arrayen s\u00e5 att Gravity Forms kan lagra v\u00e4rdet ordentligt i databasen.<\/p>\n<p>Vi kommer att beh\u00f6va transformera denna v\u00e4rdematris flera platser s\u00e5 jag kommer att definiera en separat funktion f\u00f6r detta. Funktionen accepterar den endimensionella arrayen och omvandlar den till en flerdimensionell array med de lagrade v\u00e4rdena f\u00f6r dagar och val:<\/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>Detta kommer att lagra dagnamnen och valen direkt i f\u00e4ltets v\u00e4rde. Att g\u00f6ra det p\u00e5 detta s\u00e4tt g\u00f6r det m\u00f6jligt att \u00e4ndra valen vid ett senare tillf\u00e4lle utan att bryta de gamla posterna.<\/p>\n<p>L\u00e5t oss nu \u00f6verg\u00e5 till att \u00e5sidos\u00e4tta funktionen som hanterar lagring av det inl\u00e4mnade v\u00e4rdet; <code>get_value_save_entry()<\/code>. Den kommer med fem parametrar men vi beh\u00f6ver bara den f\u00f6rsta som \u00e4r det inl\u00e4mnade v\u00e4rdet. Inuti funktionen skickar vi v\u00e4rdet till v\u00e5r anpassade funktion ovan, serialiserar dess avkastning och returnerar slutligen det nya v\u00e4rdet.<\/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>Vid det h\u00e4r laget kommer Gravity Forms att framg\u00e5ngsrikt lagra v\u00e5ra v\u00e4rderingar precis som vi vill ha dem! Men det lagrade v\u00e4rdet \u00e4r nu en serialiserad array som Gravity Forms glatt kommer att eka rakt ut. Vi m\u00e5ste implementera funktioner f\u00f6r att omvandla det fr\u00e5n en ful seriell array till en vacker utg\u00e5ng varhelst vi beh\u00f6ver den.<\/p>\n<h2>Visar det inl\u00e4mnade v\u00e4rdet<\/h2>\n<p>Det finns tre st\u00e4llen vi beh\u00f6ver f\u00f6r att \u00e4ndra produktionen av v\u00e5rt f\u00e4lts v\u00e4rde; listan \u00f6ver poster, titta p\u00e5 en enstaka post, och inom Gravity Forms sammanslagningstaggar. Merge-taggar anv\u00e4nds oftast i e-postmeddelanden. Till exempel <code>{all_fields}<\/code>\u00e4r en sammanslagningstagg som visar de fullst\u00e4ndiga inl\u00e4mnade formul\u00e4rv\u00e4rdena i e-postmeddelanden.<\/p>\n<p>Eftersom vi \u00e5terger samma utdata i tre olika fall \u00e4r det vettigt att skapa en separat funktion f\u00f6r den. Jag har definierat en anpassad funktion som accepterar v\u00e4rdet; den oserialiserade flerdimensionella arrayen, som parameter. Funktionen bygger sedan upp lite HTML som visar arrayen p\u00e5 ett vackert s\u00e4tt och returnerar str\u00e4ngen. Jag har valt en kapslad <code>&lt;ul&gt;<\/code>lista, men du kan \u00e4ndra utdata hur du vill.<\/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>Bra, l\u00e5t oss b\u00f6rja med det f\u00f6rsta: listan med poster: <code>get_value_entry_list()<\/code>. Du kan v\u00e4lja att mata ut hela resultatet h\u00e4r men det kan bli ganska klumpigt och l\u00e5ngt f\u00f6r listvyn, s\u00e5 jag har valt att helt enkelt returnera en fast str\u00e4ng som f\u00f6rklarar att anv\u00e4ndaren m\u00e5ste g\u00e5 in i ing\u00e5ngsdetaljer f\u00f6r att se den fullst\u00e4ndiga \u00f6versikten.<\/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>Detta \u00e4r naturligtvis helt upp till dig, du kan v\u00e4lja att bara visa det f\u00f6rsta x antalet tecken till exempel.<\/p>\n<p>Den andra funktionen \u00e4r den som p\u00e5verkar visningen av en enskild post: <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>Vi avserialiserar helt enkelt arrayen med WordPress-funktionen <code>[maybe_unserialize](https:\/\/developer.wordpress.org\/reference\/functions\/maybe_unserialize\/)()<\/code>och returnerar str\u00e4ngutdata fr\u00e5n v\u00e5r anpassade funktion.<\/p>\n<p>Den sista funktionen p\u00e5verkar sammanslagningstaggarna och se till att v\u00e5rt f\u00e4lts v\u00e4rde ser bra ut \u00e4ven i e-postmeddelanden: <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>Observera att vi inte beh\u00f6ver avserialisera v\u00e4rdet i den h\u00e4r funktionen.<\/p>\n<p>Med dessa tre funktioner p\u00e5 plats borde alla inskickade v\u00e4rden se ganska bra ut \u00f6verallt! Till exempel n\u00e4r du visar ett inskickat bidrag:<\/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=\"Handledning: Skapa en avancerad f\u00e4lttyp f\u00f6r anpassade gravitationsformul\u00e4r och hur man hanterar flera inmatningsv\u00e4rden\" ><\/a><\/p>\n<p>Men det saknas en viktig sak! Vid det h\u00e4r laget beh\u00e5ller inte v\u00e5ra indata de tidigare inl\u00e4mnade v\u00e4rdena och det \u00e4r ganska d\u00e5ligt.<\/p>\n<h2>F\u00e5 v\u00e5ra input att beh\u00e5lla det tidigare inl\u00e4mnade v\u00e4rdet<\/h2>\n<p>Det finns huvudsakligen tv\u00e5 fall d\u00e4r vi m\u00e5ste se till att indata h\u00e5ller de tidigare inl\u00e4mnade v\u00e4rdena. Det f\u00f6rsta fallet \u00e4r n\u00e4r en formul\u00e4rinl\u00e4mning misslyckades (till exempel anv\u00e4ndaren gl\u00f6mde ett obligatoriskt f\u00e4lt). Just nu f\u00f6rlorar alla v\u00e5ra ing\u00e5ngar alla tidigare inmatade v\u00e4rden och anv\u00e4ndaren m\u00e5ste mata in alla v\u00e4rden igen. F\u00f6r det andra n\u00e4r webbplats\u00e4garen redigerar en post fylls inte indata med de inskickade v\u00e4rdena fr\u00e5n inl\u00e4mningen \u2013 vilket g\u00f6r det ganska om\u00f6jligt att redigera v\u00e4rdena ordentligt.<\/p>\n<p>F\u00f6r att fixa detta \u00e5terg\u00e5r vi till funktionen <code>get_field_input()<\/code>. Den andra parametern till denna funktion \u00e4r v\u00e4rdet. Men kom ih\u00e5g att den h\u00e4r funktionen p\u00e5verkar b\u00e5de frontend-rendering och ing\u00e5ngsredigering. Detta \u00e4r viktigt eftersom det lagrade v\u00e4rdet \u00e4r olika i dessa tv\u00e5 fall. Om vi \u200b\u200b\u00e4r vid frontend och hanterar inl\u00e4mning av formul\u00e4r, \u00e4r v\u00e4rdet i formatet av den endimensionella array som n\u00e4mndes tidigare. Och om vi redigerar en post \u00e4r v\u00e4rdet i formatet en serialiserad flerdimensionell array. S\u00e5 vi m\u00e5ste \u00f6vers\u00e4tta det angivna v\u00e4rdet p\u00e5 r\u00e4tt s\u00e4tt f\u00f6r <code>get_field_input()<\/code>att enkelt komma \u00e5t de faktiska v\u00e4rdena.<\/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>I koden ovan, innan vi b\u00f6rjar skapa HTML f\u00f6r f\u00e4ltutdata, skapar vi en variabel <code>$table_value<\/code>som inneh\u00e5ller det korrekt \u00f6versatta v\u00e4rdet. Vi anv\u00e4nder <code>GF_Field<\/code>s funktion <code>is_entry_detail()<\/code>f\u00f6r att kontrollera om vi redigerar en post eller inte. Och sedan f\u00f6r v\u00e5ra ing\u00e5ngar \u00e4r det l\u00e4tt att komma \u00e5t de r\u00e4tta v\u00e4rdena och st\u00e4lla in dem som ing\u00e5ngarnas <code>value<\/code>attribut:<\/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>Med ovanst\u00e5ende uppdaterade <code>get_field_input()<\/code>ska alla v\u00e5ra anpassade indata alltid fyllas i med det tidigare v\u00e4rdet; oavsett om det \u00e4r att redigera en post eller f\u00f6rs\u00f6ka igen en formul\u00e4rinl\u00e4mning.<\/p>\n<p>Vid det h\u00e4r laget \u00e4r allt om rendering och lagring av v\u00e5ra v\u00e4rderingar gjort och fungerar fullt ut. Men det finns en sak till som vi definitivt m\u00e5ste fixa.<\/p>\n<h2>G\u00f6r v\u00e5rt f\u00e4ltpass &quot;obligatoriskt&quot; validering<\/h2>\n<p>Gravity Forms har kontroller f\u00f6r att se om ett f\u00e4lts v\u00e4rde \u00e4r tomt eller inte. Detta \u00e4r ofta n\u00f6dv\u00e4ndigt n\u00e4r f\u00e4ltet \u00e4r inst\u00e4llt som kr\u00e4vs. N\u00e4r ett f\u00e4lt kr\u00e4vs kan du inte skicka in formul\u00e4ret om det \u00e4r tomt, eller hur? Problemet f\u00f6r oss \u00e4r att vi har flera ing\u00e5ngar och vi vill l\u00e5ta n\u00e5gra av dem vara tomma. Detta blir ett problem om v\u00e5rt f\u00e4lt \u00e4r inst\u00e4llt p\u00e5 obligatoriskt. Gravity Forms tolkar tyv\u00e4rr &quot;\u00e4r det h\u00e4r tomt&quot; fel, och kr\u00e4ver att alla inmatningar fylls i. S\u00e5 vi m\u00e5ste l\u00e4gga till en regel som s\u00e4ger att om minst en av v\u00e5ra m\u00e5nga inmatningar \u00e4r ifyllda \u00e4r f\u00e4ltets totala v\u00e4rde inte tomt.<\/p>\n<p>Den sista funktionen vi m\u00e5ste \u00e5sidos\u00e4tta i v\u00e5r klass \u00e4r <code>is_value_submission_empty()<\/code>. Vi f\u00e5r bara formul\u00e4r-ID som parameter till denna funktion s\u00e5 vi m\u00e5ste extrahera f\u00e4ltv\u00e4rdet genom att anv\u00e4nda Gravity Forms-funktionen f\u00f6r att h\u00e4mta det fr\u00e5n <code>$_POST<\/code>arrayen: <code>rgpost('input_&lt;FIELD ID&gt;')<\/code>. Returen b\u00f6r vara den endimensionella array som vi har sett tidigare. Allt vi beh\u00f6ver g\u00f6ra \u00e4r att g\u00e5 igenom arrayen och \u00e5terv\u00e4nda <code>false<\/code>om vi hittar ett v\u00e4rde n\u00e5gonstans. Annars \u00e5terkommer vi <code>true<\/code>d\u00e5 f\u00e4ltets v\u00e4rde verkligen \u00e4r helt tomt.<\/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>Med ovanst\u00e5ende funktion p\u00e5 plats kommer v\u00e5rt f\u00e4lt inte att misslyckas med inl\u00e4mning om det \u00e4r inst\u00e4llt p\u00e5 obligatoriskt och minst en inmatning \u00e4r ifylld.<\/p>\n<h2>Slutsats och slutlig kod<\/h2>\n<p>Den h\u00e4r handledningen har visat dig i detalj hur du skapar din egen anpassade avancerade f\u00e4lttyp f\u00f6r Gravity Forms. \u00c4ven om ditt projekt \u00e4r annorlunda \u00e4n mitt exempel, hoppas jag att du har n\u00e5gra tips och a-has p\u00e5 v\u00e4gen. Jag tycker att Gravity Forms-dokumentationen \u00e4r ganska bristf\u00e4llig i vissa fall, och detta \u00e4r resultatet av mycket f\u00f6rs\u00f6k och misstag! Hur som helst, f\u00f6rhoppningsvis har detta varit till n\u00e5gon nytta f\u00f6r dig!<\/p>\n<p>F\u00f6r referens, h\u00e4r \u00e4r den fullst\u00e4ndiga koden i sin helhet:<\/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\">Inspelningsk\u00e4lla:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En handledning som visar hur man skapar en avancerad anpassad Gravity Forms-f\u00e4lttyp med flera ing\u00e5ngar med speciell hantering f\u00f6r att lagra och visa v\u00e4rdena.<\/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":[901,848,901,1110,807,807,818,818,848,868,868],"tags":[1173],"class_list":{"0":"post-233459","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","6":"hentry","7":"category-koda","8":"category-handledningar","10":"category-n-a","11":"category-php-9","13":"category-plugins-3","16":"category-wordpress-9","18":"tag-affiai-sv"},"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/233459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/comments?post=233459"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/233459\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media\/153180"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media?parent=233459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/categories?post=233459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/tags?post=233459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}