Gatsby + Drupal + Webforms

Zoals in een eerder artikel besproken moeten sommige rechten worden uitgedeeld voordat Gatsby en Drupal lekker met elkaar kunnen communiceren. Dit zijn rechten die je normaliter niet wilt uitdelen aan anonieme gebruikers dus daarvoor gebruik ik een beperkte gebruikersrol met key_auth die dan die dingen wel mag.

Formulier ophalen

Voor het gebruik van webforms in Gatsby gebruik ik de webform_jsonschema module om het formulier op te halen uit de backend. In eerste instantie had ik een paragraaf-type "webform" gemaakt zodat de gebruiker lekker zelf kon bepalen hoe-wat-waar dat formulier op de site moest komen. Echter wilde het formulier zelf (of het meest essentiƫle veld: het ID) niet meekomen. Standaard levert de JSON:API wel een array met default data en status, maar het ID is teveel gevraagd blijkbaar.

Ik dacht in eerste instantie dat dit aan het "webform in een paragraaf" concept lag, dus de Webform Node module aangezet en nog een keer proberen, maar helaas zonder het gewenste resultaat. Onder het administrator account krijg ik het veld wel mee, dus het is een permissie probleem. Na wat zoekwerk blijkt dat de rol in kwestie het recht "access any webform configuration" moet hebben om deze informatie op te halen. Daarna komt de informatie wel mee en kun je de volgende query uitvoeren:

{
  allNodeWebform {
    edges {
      node {
        id
        drupal_internal__nid
        title
        webform {
          default_data
          status
        }
        relationships {
          webform {
            drupal_internal__id
          }
        }
      }
    }
  }
}

Als je de relationships.webform.drupal_internal__id hebt, kun je vervolgens een _GET doen op /webform_jsonschema/[drupal_internal__id] en dan krijg je de formulier velden retour. Let op dat je de gebruiker ook toegang moet geven tot het REST endpoint (makkelijk te realiseren middels de REST UI module). Binnen Gatsby gebruik ik het axios component om de webform configuratie op te halen:

const axios = require('axios');
const webformEnpoint = `${process.env.GATSBY_JSON_API_BASE_URL}/webform_jsonschema/${webformId}`;
axios.get(webformEnpoint).then((response) => {
  this.setState({
    schema: response.data.schema,
    uiSchema: response.data.ui,
    csrfToken: response.data.csrfToken,
    buttons: response.data.buttons,
  });
})

Als alles goed gaat is dit het resultaat:

{
  "schema": {
    "title":"Contact",
    "type":"object",
    "required":["name","email"],
    "properties":{
      "name":{
        "title":"Your Name",
        "type":"string"
      },
      "email":{
        "title":"Your Email",
        "type":"string",
        "format":"email"
      },
    }
  },
  "ui":{
    "ui:order":["name","email","subject","message","actions"],
    "name":{
      "webform:validationErrorMessages":{"required":"Your Name is een verplicht veld."}
    },
    "email":{
      "webform:validationErrorMessages":{"required":"Your Email is een verplicht veld."}
    },
    "webform:generalValidationErrorMessage":"A form validation error occurred. Please check the values you have entered.",
    "webform:generalSubmissionErrorMessage":"There was an error submitting webform."
  },
  "buttons":[{"type":"submit","value":"Send message"}],
  "data":[],
  "csrfToken":"token"
}

Form verwerken in React

Als de JSON van het formulier binnen is verwerk ik dat met een setState() van een Webform class. Deze gebruikt een Form component van react-jsonschema-form die automagisch de formulier elementen uitleest en verwerkt naar het scherm. De submithandler in React ziet er als volgt uit:

axios({
  method: 'post',
  url: webformSubmitEndpoint,
  data: form.formData,
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': this.state.csrfToken,
  },
}).then((response) => {
  if (response.data.saved === true) {
    this.setState({
      formSuccess: true,
    });
  }
})
back_blog