Formulario con múltiples campos generado usando JSON

Hola,

Tengo un flujo de trabajo en el que quiero crear un menú desplegable con algunas fechas basadas en el envío del nodo de disparador de formulario. También me gustaría añadir una condición basada en el botón de radio seleccionado en el nodo de disparador de formulario. Creé un nodo de código JSON como en el archivo adjunto. Sin embargo, tengo un problema para construir adecuadamente el siguiente formulario (nodo “Add dates” en el flujo de trabajo adjunto). Quiero que muestre dos campos: el menú desplegable etiquetado como “form fields” y la entrada de texto etiquetada como “NIP”. Desafortunadamente, o bien muestra solo un campo (como en el flujo de trabajo adjunto) o, después de algunas modificaciones, genera un error “not valid json”. ¿Alguien tiene alguna idea de cómo construir este nodo para lograr mi objetivo?

{
  "name": "[2.9] Zadanie domowe - formularz szkolenia",
  "nodes": [
    {
      "parameters": {
        "formTitle": "Formularz zapisu na szkolenie",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Imię i nazwisko:",
              "placeholder": "Jan Kowalski",
              "requiredField": true
            },
            {
              "fieldLabel": "e-mail:",
              "fieldType": "email",
              "placeholder": "a@b.cd",
              "requiredField": true
            },
            {
              "fieldLabel": "Telefon:",
              "placeholder": "+48 123 456 789",
              "requiredField": true
            },
            {
              "fieldLabel": "Bierzesz udział jako:",
              "fieldType": "radio",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Firma"
                  },
                  {
                    "option": "Osoba prywatna"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.5,
      "position": [
        0,
        0
      ],
      "id": "28e29a54-80a4-4197-af04-2389d4a3221e",
      "name": "On form submission",
      "webhookId": "67fa2c56-27e9-470d-968e-a352bef94e20"
    },
    {
      "parameters": {
        "operation": "completion",
        "completionTitle": "={{ $if($json != null, \"Sukces!\", \"Oj, coś poszło nie tak...\") }}",
        "completionMessage": "={{ $json.summary[0].fieldLabel }}",
        "options": {}
      },
      "type": "n8n-nodes-base.form",
      "typeVersion": 2.5,
      "position": [
        768,
        0
      ],
      "id": "c9cb7630-fdf6-4d2e-8c74-45f660e4c518",
      "name": "Form",
      "webhookId": "3ae63389-41aa-41c6-ae51-5b8cba10bb13"
    },
    {
      "parameters": {
        "defineForm": "json",
        "jsonOutput": "={{ $json.formFields, $json.NIP }}",
        "options": {}
      },
      "type": "n8n-nodes-base.form",
      "typeVersion": 2.5,
      "position": [
        416,
        0
      ],
      "id": "6f462d5f-f41b-4f5b-afc1-333de809002f",
      "name": "Add Dates",
      "webhookId": "f58ff39c-4aeb-49b9-a448-5f843494f823"
    },
    {
      "parameters": {
        "jsCode": "const label = \"Droga/Drogi \" + $(\"Calculate dates and NIP\").first().json[\"Imię i nazwisko:\"] + \".\\nZostałaś/zostałeś pomyślnie zarejestrowana/zarejestrowany na szkolenie w dniu:\\n\" + $input.first().json[\"Wybierz termin\"];\n\nconst formFields = [\n  {\n    fieldLabel: label\n  }\n];\n\nreturn [{\n  json: {\n    summary: formFields\n  }\n}]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        592,
        0
      ],
      "id": "b31b8584-6b17-4411-84b9-9f28378389f4",
      "name": "Success Summary Text"
    },
    {
      "parameters": {
        "jsCode": "const availableDates = Array.from({ length: 6 }, (_, offset) =\
      {
  const dayOffset = (today) =\
      {
    let off = 2 - today;
    return off;
  }
  
  const date = $now.plus({ weeks: offset + 1, days: dayOffset(DateTime.local().weekday) });

  
  return {
    option: date.toFormat('dd.MM.yyyy')
  };
});\n\nconst formFields = [\n  {\n    fieldLabel: \"Wybierz termin\",\n    fieldType: \"dropdown\",\n    requiredField: true,\n    fieldOptions: {\n      values: availableDates\n    }\n  }\n];\n\nconst nipInput = ($input.first().json[\"Bierzesz udział jako:\"] === \"Firma\" ? [\n  {\n    fieldLabel: \"Podaj NIP\",\n    fieldType: \"text\",\n    requiredField: true\n  }\n] : null );\n\nreturn [{\n  json: {\n    ...$input.first().json,\n    formFields: formFields,\n    NIP: nipInput,\n    //availableDates: availableDates.map(d =\
      d.option)\n  }\n}]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        0
      ],
      "id": "57f1ca26-2ddb-4b49-b670-e83845632a8f",
      "name": "Calculate dates and NIP"
    }
  ],
  "pinData": {},
  "connections": {
    "On form submission": {
      "main": [
        [
          {
            "node": "Calculate dates and NIP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Dates": {
      "main": [
        [
          {
            "node": "Success Summary Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Success Summary Text": {
      "main": [
        [
          {
            "node": "Form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate dates and NIP": {
      "main": [
        [
          {
            "node": "Add Dates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "b4b36e4b-ee4d-4192-bf1d-c271d725b0b0",
  "meta": {
    "instanceId": "6bf048c6d4d3d2ea0ff37f1fadbd0c376cd8e3dfc89fd11ea9adc8fc9affaad7"
  },
  "id": "DmjAWBhbgcnJsCAo",
  "tags": []
}
1 me gusta

Hola @Michal_Moraszczyk

¿Puedes probar esto?

2 Me gusta

Hola Michal,

El problema probablemente esté en cómo tu nodo Code devuelve el JSON. El nodo Form espera un array JSON en el nivel superior del output — no anidado dentro de un objeto ni envuelto en una cadena de texto.

Aquí te muestro la estructura correcta para tu nodo Form “Add dates” (configurado en “Define form using JSON”):

[
  {
    "fieldLabel": "Select Date",
    "fieldType": "dropdown",
    "fieldOptions": {
      "values": [
        { "option": "your_dynamic_date_1" },
        { "option": "your_dynamic_date_2" }
      ]
    },
    "requiredField": true
  },
  {
    "fieldLabel": "NIP",
    "fieldType": "text",
    "placeholder": "Enter NIP",
    "requiredField": true
  }
]

Errores comunes que causan “not valid json” o que solo aparezca un campo:

  1. Envolver en un objeto — No devuelvas { "fields": [...] }. El nodo Form espera el array directamente. Devuelve solo el array.

  2. Devolver como una cadena de texto — Si tu nodo Code hace JSON.stringify(), el nodo Form recibe una cadena en lugar de un objeto parseado. Devuelve el array como un objeto real.

  3. Múltiples elementos en lugar de uno — Tu nodo Code debe devolver un único elemento que contenga el array completo. Usa este patrón en tu nodo Code:

const fields = [
  {
    fieldLabel: "Select Date",
    fieldType: "dropdown",
    fieldOptions: {
      values: dates.map(d => ({ option: d }))
    },
    requiredField: true
  },
  {
    fieldLabel: "NIP",
    fieldType: "text",
    placeholder: "Enter NIP",
    requiredField: true
  }
];

return [{ json: fields }];

La parte clave es return [{ json: fields }] — un único elemento, y el array va dentro de json. Esto es lo que la mayoría olvida.

Para la condición del botón de radio — usa un nodo IF después del Form Trigger para ramificar, y conecta la rama correcta al nodo Form “Add dates”. Cada rama puede tener su propio nodo Form con definiciones de campos diferentes.

¡Espero que esto te ayude!

1 me gusta

¡Hola!

¡Tu solución me funcionó perfectamente! ¡Gracias!

1 me gusta

Hola,

¡Tu explicación es exhaustiva y valiosa! Tendré en cuenta tu recomendación - serán de ayuda también en mis flujos de trabajo futuros. ¡Gracias!