{"id":31870,"date":"2025-04-29T16:51:19","date_gmt":"2025-04-29T21:51:19","guid":{"rendered":"https:\/\/wpengine.com\/builders\/?p=31870"},"modified":"2025-04-30T17:11:40","modified_gmt":"2025-04-30T22:11:40","slug":"dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue","status":"publish","type":"post","link":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/","title":{"rendered":"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue"},"content":{"rendered":"\n<p><a href=\"https:\/\/wpengine.com\/builders\/gravity-forms-in-headless-wordpress-with-nuxt-vue\/\">In part one of this series<\/a>, we built a headless Gravity Forms integration with Nuxt\/Vue by querying form fields via GraphQL interfaces and mapping each static type to its own Vue component\u2014consolidating shared inputs into reusable <code>InputField<\/code>, <code>DropdownField<\/code>, and <code>ChoiceListField<\/code> components. While that approach gives you fine\u2011grained control and clear component boundaries, it also means maintaining a growing switch statement (and import list) whenever you add or customize a field type.<\/p>\n\n\n\n<p>In this second part article, we\u2019ll streamline our setup by leveraging the <code>inputType<\/code> property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, we\u2019ll implement a single <code>resolveFieldComponent(field)<\/code> helper that dynamically loads the right Vue component.&nbsp;<\/p>\n\n\n\n<p>This makes our form renderer more flexible, reduces boilerplate, and automatically adapts to new or custom Gravity Forms fields as they\u2019re added.\u00a0<br><br>If you prefer video format, please see below:<br><\/p>\n\n\n\n<iframe class=\"youtube-video\"  src=\"https:\/\/www.youtube.com\/embed\/uDjUPXvG-64\" title=\"YouTube video player\" frameborder=\"0\" style=\"display: block; margin: auto; width: 100%; height: 400px;\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n\n\n\n<div class=\"wp-block-group has-polar-background-color has-background is-layout-flow wp-container-core-group-is-layout-7a03825d wp-block-group-is-layout-flow\" style=\"padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--40)\">\n<p class=\"has-large-font-size\"><strong>Table of Contents<\/strong><\/p>\n\n\n\n<ul id=\"Prerequisites\" class=\"wp-block-list\">\n<li><a href=\"#prerequisites\">Prerequisites<\/a><\/li>\n\n\n\n<li><a href=\"#the-inputfield-vue-file\">The InputField.vue File<\/a><\/li>\n\n\n\n<li><a href=\"#why-some-fields-retain-custom-components\">Why Some Fields Retain Custom Components<\/a><\/li>\n\n\n\n<li><a href=\"#the-useformfields-js-file\">The useFormFields.js File<\/a><\/li>\n\n\n\n<li><a href=\"#questionnaire-index-vue-file\">The pages\/questionnaire\/index.vue File<\/a><\/li>\n\n\n\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading prerequisites\">Prerequisites<\/h2>\n\n\n\n<p>Before diving in, you\u2019ll need a working knowledge of the command line,<a href=\"https:\/\/wpengine.com\/builders\/headless-roadmap\/\"> headless WordPress development<\/a>, <a href=\"https:\/\/vuejs.org\/\">Vue<\/a>, and <a href=\"https:\/\/nuxt.com\/\">Nuxt<\/a>.&nbsp;<\/p>\n\n\n\n<p>This guide is the second installment in my series. If you haven\u2019t already, please read<a href=\"https:\/\/wpengine.com\/builders\/gravity-forms-in-headless-wordpress-with-nuxt-vue\/\"> Part 1: Gravity Forms in Headless WordPress with Nuxt\/Vue<\/a> and explore its accompanying code repository to benefit from this article.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Now, let\u2019s dive in and refactor our Nuxt app for dynamic field rendering. <\/p>\n\n\n\n<p>We will be refactoring the three files we will be using: the <code>InputField. vue<\/code>, <code>useFormFields.js<\/code>, and the <code>pages\/questionnaire\/index.vue<\/code> files.&nbsp;&nbsp;<br><\/p>\n\n\n\n<p>For your reference, here is the fully refactored project <a href=\"https:\/\/github.com\/Fran-A-Dev\/nuxt3-headlesswp-gravity-forms\/tree\/dynamic-inputType-example\">repo for dynamic field rendering<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-inputfield-vue-file\">The <code>InputField.vue<\/code> File<\/h2>\n\n\n\n<p>In your <code>components\/form-fields <\/code>directory, you can safely delete <code>EmailField.vue<\/code>.&nbsp; In the original article, we already consolidated <code>TextField.vue<\/code>, and <code>WebsiteField.vue<\/code>.&nbsp;<\/p>\n\n\n\n<p>Now, we\u2019ll add the email field to <code>InputField.vue<\/code> to handle all three field types (text, email, and website). Here\u2019s the full code for <code>InputField.vue<\/code> that you can drop straight into your project:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field-wrapper\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">v-if<\/span>=<span class=\"hljs-string\">\"field.label\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">:for<\/span>=<span class=\"hljs-string\">\"field.databaseId\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"block text-sm font-medium text-gray-700\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">    &gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>      {{ field.label }}\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">v-if<\/span>=<span class=\"hljs-string\">\"field.isRequired\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"text-red-500\"<\/span>&gt;<\/span>*<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">:id<\/span>=<span class=\"hljs-string\">\"field.databaseId\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">:type<\/span>=<span class=\"hljs-string\">\"computedInputType\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"internalValue\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">:placeholder<\/span>=<span class=\"hljs-string\">\"field.placeholder || defaultPlaceholder\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">:required<\/span>=<span class=\"hljs-string\">\"field.isRequired\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">      <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500\"<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">    \/&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">setup<\/span>&gt;<\/span><span class=\"javascript\"><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">import<\/span> { computed } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"vue\"<\/span>;<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> props = defineProps({<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\">  <span class=\"hljs-attr\">field<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Object<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\">  <span class=\"hljs-attr\">modelValue<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">default<\/span>: <span class=\"hljs-string\">\"\"<\/span> },<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\">});<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> emit = defineEmits(&#91;<span class=\"hljs-string\">\"update:modelValue\"<\/span>]);<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-comment\">\/\/ Use a computed property for two-way binding.<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> internalValue = computed({<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\">  <span class=\"hljs-attr\">get<\/span>: <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> props.modelValue,<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">  <span class=\"hljs-attr\">set<\/span>: <span class=\"hljs-function\">(<span class=\"hljs-params\">val<\/span>) =&gt;<\/span> emit(<span class=\"hljs-string\">\"update:modelValue\"<\/span>, val),<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\">});<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-comment\">\/\/ Determine the input type based on the field type (or optionally inputType if available)<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">const<\/span> computedInputType = computed(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">  <span class=\"hljs-keyword\">const<\/span> type = (props.field.inputType || props.field.type || <span class=\"hljs-string\">\"\"<\/span>).toUpperCase();<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">  <span class=\"hljs-keyword\">if<\/span> (type === <span class=\"hljs-string\">\"EMAIL\"<\/span>) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"email\"<\/span>;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">  <span class=\"hljs-keyword\">if<\/span> (type === <span class=\"hljs-string\">\"WEBSITE\"<\/span>) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"url\"<\/span>;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">  <span class=\"hljs-comment\">\/\/ Default to text input for TEXT or TEXTAREA, etc.<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"text\"<\/span>;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\">});<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\"><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-comment\">\/\/ Default placeholder text if none is provided.<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">const<\/span> defaultPlaceholder = <span class=\"hljs-string\">\"Enter value...\"<\/span>;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-function\"><\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">style<\/span> <span class=\"hljs-attr\">scoped<\/span>&gt;<\/span><span class=\"css\"><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"css\"><span class=\"hljs-selector-class\">.field-wrapper<\/span> {<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"css\">  <span class=\"hljs-attribute\">margin-bottom<\/span>: <span class=\"hljs-number\">1rem<\/span>;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"css\">}<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-function\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"css\"><\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">style<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I am not going to go over the entire code.&nbsp; Here are the bullet points on why this works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Single responsibility<\/strong>: One component now handles text, email, and website inputs.<br><\/li>\n\n\n\n<li><strong>Dynamic <\/strong><strong>&lt;input&gt;<\/strong><strong> types<\/strong>: The computedInputType maps your GraphQL inputType (or fallback type) to email, url, or text.<br><\/li>\n\n\n\n<li><strong>Two\u2011way binding<\/strong>: Using v-model on a local<code> internalValue <\/code>ensures that parent components stay in sync without extra boilerplate.<br><\/li>\n<\/ul>\n\n\n\n<p><strong>Conditional label &amp; required indicator<\/strong>: The <code>&lt;label&gt;<\/code> only renders if <code>field.label<\/code> is present, and the red asterisk appears when <code>field.isRequired<\/code> is true.<\/p>\n\n\n\n<p>By consolidating these three nearly identical components into <code>InputField.vue<\/code>, you keep your code DRY (Don\u2019t Repeat Yourself) and maintainable\u2014any future tweaks to generic inputs (styling, validation attributes, accessibility features) happen in one place.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"why-some-fields-retain-custom-components\">Why Some Fields Retain Custom Components<\/h3>\n\n\n\n<p>Even with our dynamic mapping in place, you will notice a handful of Gravity Forms fields that still warrant their own dedicated Vue components. These \u201ccomposite\u201d fields each have unique markup or behavior that goes beyond a simple single\u2011element input.<\/p>\n\n\n\n<p>By keeping these specialized components, we preserve clarity and maintainability\u2014each one encapsulates its own layout, validation rules, and third\u2011party widget integrations. All the other \u201csimple\u201d fields (text, email, URL, select, checkbox, radio, etc.) are routed through our generic <code>InputField<\/code>, <code>DropdownField<\/code>, or <code>ChoiceListField<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-useformfields-js-file\">The <code>useFormFields.js<\/code> File<\/h2>\n\n\n\n<p>Next, let\u2019s look at how we dynamically map each Gravity Forms field to its Vue component using a single composable. Update your <code>composables\/useFormFields.js<\/code> with the following:<br><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">import<\/span> { defineAsyncComponent } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"vue\"<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ Cache to store component references keyed by field type.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> componentCache = {};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ Mapping from field type to component filename.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> typeToComponent = {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">ADDRESS<\/span>: <span class=\"hljs-string\">\"AddressField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">TEXT<\/span>: <span class=\"hljs-string\">\"InputField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">TEXTAREA<\/span>: <span class=\"hljs-string\">\"InputField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">EMAIL<\/span>: <span class=\"hljs-string\">\"InputField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">NAME<\/span>: <span class=\"hljs-string\">\"NameField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">PHONE<\/span>: <span class=\"hljs-string\">\"PhoneField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">SELECT<\/span>: <span class=\"hljs-string\">\"DropdownField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">MULTISELECT<\/span>: <span class=\"hljs-string\">\"DropdownField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">CHECKBOX<\/span>: <span class=\"hljs-string\">\"ChoiceListField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">RADIO<\/span>: <span class=\"hljs-string\">\"ChoiceListField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">DATE<\/span>: <span class=\"hljs-string\">\"DateField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">TIME<\/span>: <span class=\"hljs-string\">\"TimeField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attr\">WEBSITE<\/span>: <span class=\"hljs-string\">\"InputField\"<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> useFormFields = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ For debugging purposes, you can track which types are processed.<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> loggedTypes = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Set<\/span>();\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/**<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">   * Resolves the Vue component for a given field based on its inputType.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">   * Uses a cache so that the same component reference is returned for a given type.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">   * @param {Object} field - The Gravity Form field object.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">   * @returns {Component|null} The async Vue component for this field.<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">   *\/<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">const<\/span> resolveFieldComponent = <span class=\"hljs-function\">(<span class=\"hljs-params\">field<\/span>) =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> fieldType = field.inputType\n<\/span><\/span><span class='shcb-loc'><span>      ? field.inputType.toUpperCase()\n<\/span><\/span><span class='shcb-loc'><span>      : field.type.toUpperCase();\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Add each field type once<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> (!loggedTypes.has(fieldType)) {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Mapping field type:\"<\/span>, fieldType);\n<\/span><\/span><span class='shcb-loc'><span>      loggedTypes.add(fieldType);\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Return from cache if we\u2019ve already loaded this component<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> (componentCache&#91;fieldType]) {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-keyword\">return<\/span> componentCache&#91;fieldType];\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Dynamically import the matching component<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> componentName = typeToComponent&#91;fieldType];\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">if<\/span> (componentName) {\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-keyword\">const<\/span> asyncComponent = defineAsyncComponent(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>        <span class=\"hljs-keyword\">import<\/span>(<span class=\"hljs-string\">`~\/components\/form-fields\/<span class=\"hljs-subst\">${componentName}<\/span>.vue`<\/span>)\n<\/span><\/span><span class='shcb-loc'><span>      );\n<\/span><\/span><span class='shcb-loc'><span>      componentCache&#91;fieldType] = asyncComponent;\n<\/span><\/span><span class='shcb-loc'><span>      <span class=\"hljs-keyword\">return<\/span> asyncComponent;\n<\/span><\/span><span class='shcb-loc'><span>    }\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ Fallback if no mapping exists<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">null<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  };\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">return<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>    resolveFieldComponent,\n<\/span><\/span><span class='shcb-loc'><span>  };\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>What is happening in this code block:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Dynamic Resolution<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Instead of hard\u2011coding imports for every field type, we use the field\u2019s inputType (or fallback to type) to look up the correct component in a simple map.<\/p>\n\n\n\n<p><strong>Lazy Loading<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We wrap each import in defineAsyncComponent, so components are only fetched when they\u2019re actually rendered\u2014improving initial load times.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Component Caching<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Once a component is resolved, we store the reference in componentCache. This ensures we don\u2019t re\u2011import the same file multiple times, keeping render performance snappy.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DRY and Scalable<\/strong><\/li>\n<\/ul>\n\n\n\n<p>As new field types are added in Gravity Forms (or you build custom ones), you simply extend the typeToComponent map. No more boilerplate imports or switch statements cluttering your page component.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Debugging Insight<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The loggedTypes set and console messages help you verify which field types are encountered at render time, making it easier to spot missing mappings.<\/p>\n\n\n\n<p>By centralizing all your field\u2011component logic in useFormFields.js, you maintain a clean separation of concerns.&nbsp; Your page doesn\u2019t need to know about every single component, and your mapping stays in one easy\u2011to\u2011update place.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"questionnaire-index-vue-file\">The <code>pages\/questionnaire\/index.vue<\/code> File<\/h2>\n\n\n\n<p>Finally, let\u2019s update our page component to use <code>resolveFieldComponent <\/code>instead of a static map. <code>In pages\/questionnaire\/index.vue<\/code>, replace all manual imports and the <code>fieldComponents<\/code> object with a single import of your composable:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">setup<\/span>&gt;<\/span><span class=\"javascript\"><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">import<\/span> { ref, reactive, onMounted, watch } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'vue'<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">import<\/span> { useFormFields } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'~\/composables\/useFormFields'<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">import<\/span> useGravityForm <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'~\/composables\/useGravityForm'<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> { resolveFieldComponent } = useFormFields()<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> { fetchForm, submitForm, formFields } = useGravityForm()<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> formValues = ref({})<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> error       = ref(<span class=\"hljs-literal\">null<\/span>)<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-keyword\">const<\/span> validationErrors = reactive({ <span class=\"hljs-comment\">\/* ... *\/<\/span> })<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-comment\">\/\/ (validation helpers and updateFieldValue omitted for brevity)<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\">onMounted(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {<\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">  <span class=\"hljs-keyword\">const<\/span> { data, <span class=\"hljs-attr\">error<\/span>: fetchError, execute } = fetchForm()<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">  execute()<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">  watch(data, (newData) =&gt; { <span class=\"hljs-comment\">\/* initialize formValues *\/<\/span> })<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">  watch(fetchError, (err) =&gt; { <span class=\"hljs-keyword\">if<\/span> (err) error.value = err.message })<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\">})<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">const<\/span> handleSubmit = <span class=\"hljs-keyword\">async<\/span> () =&gt; { <span class=\"hljs-comment\">\/* ... *\/<\/span> }<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-function\"><\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">template<\/span>&gt;<\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"p-4\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">v-if<\/span>=<span class=\"hljs-string\">\"error\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"text-red-600\"<\/span>&gt;<\/span>Error: {{ error }}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">v-else-if<\/span>=<span class=\"hljs-string\">\"!formFields.length\"<\/span>&gt;<\/span>Loading form\u2026<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">v-else<\/span> @<span class=\"hljs-attr\">submit.prevent<\/span>=<span class=\"hljs-string\">\"handleSubmit\"<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"field in formFields\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-attr\">:key<\/span>=<span class=\"hljs-string\">\"field.databaseId\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-4\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      &gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">component<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">:is<\/span>=<span class=\"hljs-string\">\"resolveFieldComponent(field)\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">:field<\/span>=<span class=\"hljs-string\">\"field\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">          <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"formValues&#91;field.databaseId]\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        \/&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"bg-blue-500 text-white px-4 py-2 rounded\"<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      &gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">        Submit<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\"><span class=\"javascript\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\"><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the part of the file we refactored, we now have a single source of truth. Instead of importing each individual field component and maintaining a <code>fieldComponents<\/code> object, we now call <code>resolveFieldComponent(field)<\/code> directly in a template.<\/p>\n\n\n\n<p>Let\u2019s go over the rest of the code block:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cleaner Imports<\/strong><\/li>\n<\/ul>\n\n\n\n<p>We only import <code>useFormFields<\/code> (for dynamic mapping) and <code>useGravityForm<\/code> (for data). There are no longer dozens of component imports at the top.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Reactive Rendering<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The <code>&lt;component :is=\"\u2026\"&gt;<\/code> syntax picks the right component at render time, based solely on each field\u2019s<code> inputType<\/code> or type.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Simplified Maintenance<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Adding support for new field types now only requires updating the <code>typeToComponent<\/code> map in <code>useFormFields.js<\/code>, not touching this page at all.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Consistent v-model<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Leveraging <code>v-model<\/code> with each dynamically resolved component ensures two\u2011way binding of all field values without extra boilerplate.<\/p>\n\n\n\n<p>By swapping out static maps for <code>resolveFieldComponent<\/code>your <code>index.vue<\/code> becomes significantly more concise, and all field\u2011to\u2011component logic lives in one easy\u2011to\u2011update composable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>We hope this article helped you understand how to render dynamic fields in WPGraphQL for Gravity Forms in Nuxt.js!&nbsp;<\/p>\n\n\n\n<p>As always, we\u2019re super stoked to hear your feedback and learn about the headless projects you\u2019re working on, so hit us up in the <a href=\"https:\/\/wpeng.in\/devrel-discord\/\">Headless WordPress Discord<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In part one of this series, we built a headless Gravity Forms integration with Nuxt\/Vue by querying form fields via GraphQL interfaces and mapping each static type to its own [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"footnotes":""},"categories":[23],"tags":[],"class_list":["post-31870","post","type-post","status-publish","format-standard","hentry","category-headless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue - Builders<\/title>\n<meta name=\"description\" content=\"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue\" \/>\n<meta property=\"og:description\" content=\"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/\" \/>\n<meta property=\"og:site_name\" content=\"Builders\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-29T21:51:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-30T22:11:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Untitled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Francis Agulto\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:site\" content=\"@wpebuilders\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Francis Agulto\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/\"},\"author\":{\"name\":\"Francis Agulto\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/bcdcb4ac0b215c34b6b30e440a24dc54\"},\"headline\":\"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\\\/Vue\",\"datePublished\":\"2025-04-29T21:51:19+00:00\",\"dateModified\":\"2025-04-30T22:11:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/\"},\"wordCount\":993,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"articleSection\":[\"Headless\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/\",\"name\":\"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\\\/Vue - Builders\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\"},\"datePublished\":\"2025-04-29T21:51:19+00:00\",\"dateModified\":\"2025-04-30T22:11:40+00:00\",\"description\":\"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\\\/Vue\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#website\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"name\":\"Builders\",\"description\":\"Reimagining the way we build with WordPress.\",\"publisher\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#organization\",\"name\":\"WP Engine\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"contentUrl\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/WP-Engine-Horizontal@2x.png\",\"width\":348,\"height\":68,\"caption\":\"WP Engine\"},\"image\":{\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/wpebuilders\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCh1WuL54XFb9ZI6m6goFv1g\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/#\\\/schema\\\/person\\\/bcdcb4ac0b215c34b6b30e440a24dc54\",\"name\":\"Francis Agulto\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g\",\"caption\":\"Francis Agulto\"},\"description\":\"Fran Agulto is a Developer Advocate at WP Engine. He is a lover of all things headless WordPress, Rock Climbing, and overall being stoked for people that love what they do and share that stoke with others! Follow me on Twitter for cool stoked headless WP!\",\"url\":\"https:\\\/\\\/wpengine.com\\\/builders\\\/author\\\/francis-agultowpengine-com-2-2-2-2-2-2-2-2-2-2-2-3\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue - Builders","description":"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/","og_locale":"en_US","og_type":"article","og_title":"Dynamic Field Rendering with Gravity Forms in Headless WP & Nuxt\/Vue","og_description":"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.","og_url":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/","og_site_name":"Builders","article_published_time":"2025-04-29T21:51:19+00:00","article_modified_time":"2025-04-30T22:11:40+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2025\/04\/Untitled.png","type":"image\/png"}],"author":"Francis Agulto","twitter_card":"summary_large_image","twitter_creator":"@wpebuilders","twitter_site":"@wpebuilders","twitter_misc":{"Written by":"Francis Agulto","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/#article","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/"},"author":{"name":"Francis Agulto","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/bcdcb4ac0b215c34b6b30e440a24dc54"},"headline":"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue","datePublished":"2025-04-29T21:51:19+00:00","dateModified":"2025-04-30T22:11:40+00:00","mainEntityOfPage":{"@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/"},"wordCount":993,"commentCount":0,"publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"articleSection":["Headless"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/","url":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/","name":"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue - Builders","isPartOf":{"@id":"https:\/\/wpengine.com\/builders\/#website"},"datePublished":"2025-04-29T21:51:19+00:00","dateModified":"2025-04-30T22:11:40+00:00","description":"Learn to leverage the inputType property that WPGraphQL for Gravity Forms exposes on every field. Instead of manually importing and mapping each component, discover how to implement a single resolveFieldComponent(field) helper that dynamically loads the right Vue component.","breadcrumb":{"@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/wpengine.com\/builders\/dynamic-field-rendering-with-gravity-forms-in-headless-wp-nuxt-vue\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wpengine.com\/builders\/"},{"@type":"ListItem","position":2,"name":"Dynamic Field Rendering with Gravity Forms in Headless WP &amp; Nuxt\/Vue"}]},{"@type":"WebSite","@id":"https:\/\/wpengine.com\/builders\/#website","url":"https:\/\/wpengine.com\/builders\/","name":"Builders","description":"Reimagining the way we build with WordPress.","publisher":{"@id":"https:\/\/wpengine.com\/builders\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wpengine.com\/builders\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/wpengine.com\/builders\/#organization","name":"WP Engine","url":"https:\/\/wpengine.com\/builders\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/","url":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","contentUrl":"https:\/\/wpengine.com\/builders\/wp-content\/uploads\/2024\/05\/WP-Engine-Horizontal@2x.png","width":348,"height":68,"caption":"WP Engine"},"image":{"@id":"https:\/\/wpengine.com\/builders\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/wpebuilders","https:\/\/www.youtube.com\/channel\/UCh1WuL54XFb9ZI6m6goFv1g"]},{"@type":"Person","@id":"https:\/\/wpengine.com\/builders\/#\/schema\/person\/bcdcb4ac0b215c34b6b30e440a24dc54","name":"Francis Agulto","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0c8a05c76944fc987d57296c96dc368055844527088c0aa44297edbfa8b82546?s=96&d=mm&r=g","caption":"Francis Agulto"},"description":"Fran Agulto is a Developer Advocate at WP Engine. He is a lover of all things headless WordPress, Rock Climbing, and overall being stoked for people that love what they do and share that stoke with others! Follow me on Twitter for cool stoked headless WP!","url":"https:\/\/wpengine.com\/builders\/author\/francis-agultowpengine-com-2-2-2-2-2-2-2-2-2-2-2-3\/"}]}},"_links":{"self":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/comments?post=31870"}],"version-history":[{"count":0,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/posts\/31870\/revisions"}],"wp:attachment":[{"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/media?parent=31870"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/categories?post=31870"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpengine.com\/builders\/wp-json\/wp\/v2\/tags?post=31870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}