Gatsby – WordPress: contactformulier

Gatsby – WordPress: contactformulier

Dit artikel behandelt een van de methoden voor het maken van een contactformulier in Gatsby.js, waarbij de gegevens uit de WordPress-database worden opgehaald via GraphQl.

Je hebt wel wat vaardigheden nodig op het gebied van coderen in JS, React, PHP en enige kennis van WordPress-functies.

De bibliotheken die hier zullen worden gebruikt zijn:

Reageer Apollo
Formik
Formik Semantische gebruikersinterface Reageren
JEP

Laten we beginnen met het installeren van alle bovengenoemde bibliotheken.

Open in de terminal de hoofdmap van Gatsby instance en dan

npm i react-apollo formik formik-semantic-ui-react yup

Om ons formulier werkend te krijgen, moeten we het ook in Gatsby en WordPress programmeren. Laten we beginnen bij het Gatsby-gedeelte.

Maak in de map root/src een nieuwe submap. Waarom noemen we het niet “mutaties”. Dan maken we een nieuw bestand aan. Om een logica in onze naamgevingsconventie te houden, noemen we het ContactFormMutation.js.


import { gql } from '@apollo/client';

const CONTACT = gql`
    mutation CONTACT ($clientMutationId: String!, $name: String!, $phone: String!, $company: String!,  $email: String! $message: String!) {
        createContact(
            input: {
                clientMutationId: $clientMutationId,
                name: $name,
                phone: $phone,
                company: $company,
                email: $email,
                message: $message,
            }
        ) {
            success
            data
        }
    }
`;

export default CONTACT;

Nu kunnen we een contactformuliercomponent maken. Om een logica in een bestandsstructuur te houden, laten we een nieuwe map “ContactForm” maken in de map root/componenten. Vervolgens moeten we daar een nieuw bestand maken: ContactForm.js.

We zullen profiteren van de React-status, Yup-validatie en Formik-functionaliteit.


import React from 'react';
import PropTypes from 'prop-types';
import { Mutation } from 'react-apollo';
import {
    Form, Input, SubmitButton, TextArea,
} from 'formik-semantic-ui-react';
import { Formik } from 'formik';
import * as Yup from 'yup';
import CONTACT from '../../mutations/ContactFormMutation';

const initialValues = {
    email: 'a@a.com',
};

const validationSchema = Yup.object({
    name: Yup.string().required(),
    email: Yup.string().email('Incorrect email address').required('Required'),
    phone: Yup.string().matches(new RegExp('[0-9]{7}'), 'Incorrect phone number').required('Required),
});

class ContactForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            formStatus: 'unsubmitted',
            email: '',
            name: '',
            company: '',
            phone: '',
            message: '',
            errorList: [],
        };
        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(event) {
        const { target } = event;
        let value = '';
        let name = '';
        value = target.value;
        name = target.name;
        this.setState({
            [name]: value,
        });
    }

    form() {
        const formState = this.state;
        const emailState = formState.email;
        const nameState = formState.name;
        const phoneState = formState.phone;
        const messageState = formState.message;
        const companyState = formState.company;
        return (
            <div className="contact__form-container">
                <Mutation
                    mutation={CONTACT}
                    onCompleted={(response) => {
                        if (response.createContact.success === true) {
                            this.setState({ formStatus: 'submitted' });
                        } else {
                            this.setState({ formStatus: 'error' });
                            const errors = JSON.parse(response.createContact.data);
                            this.setState({ errorList: errors });
                        }
                    }}
                    onError={() => {
                        this.setState({ formStatus: 'error' });
                    }}
                >
                    {(addContact) => (
                        <Formik
                            initialValues={initialValues}
                            enableReinitialize
                            validationSchema={validationSchema}
                            onSubmit={(async_, { setSubmitting }) => {
                                setTimeout(() => {
                                    this.setState({ formStatus: 'loading' });
                                    addContact({
                                        variables: {
                                            clientMutationId: 'createContact',
                                            email: emailState,
                                            name: nameState,
                                            phone: phoneState,
                                            company: companyState,
                                            message: messageState,
                                        },
                                    });
                                    setSubmitting(false);
                                }, 1000);
                            }}
                        >
                            {({ isValid, dirty }) => (
                                <Form size={formSize}>
                                    <div className="row">
                                        <div className="col">
                                            <Input
                                                id="name"
                                                name="name"
                                                placeholder="Name"
                                                focus
                                                errorPrompt
                                                value={nameState}
                                                onChange={this.handleInputChange}
                                            />
                                        </div>
                                        <div className="col">
                                            <Input
                                                id="email"
                                                name="email"
                                                placeholder="Email"
                                                focus
                                                errorPrompt
                                                value={emailState}
                                                onChange={this.handleInputChange}
                                            />
                                        </div>
                                    </div>
                                    <div className="row">
                                        <div className="col">
                                            <Input
                                                id="phone"
                                                name="phone"
                                                placeholder="Phone"
                                                focus
                                                errorPrompt
                                                value={phoneState}
                                                onChange={this.handleInputChange}
                                            />
                                        </div>
                                        <div className="col">
                                            <Input
                                                id="Company"
                                                name="company"
                                                placeholder="Company"
                                                focus
                                                errorPrompt
                                                value={companyState}
                                                onChange={this.handleInputChange}
                                            />
                                        </div>
                                    </div>
                                    <div className="row">
                                        <div className="col">
                                            <TextArea
                                                id="message"
                                                name="message"
                                                placeholder="Message"
                                                focus={true.toString()}
                                                errorPrompt
                                                style={{ minHeight: 60 }}
                                                value={messageState}
                                                onChange={this.handleInputChange}
                                            />
                                        </div>
                                    </div>
                                    <div className="row">
                                        <div className="col" />
                                        <div className="col">
                                            <SubmitButton
                                                className="wc-button-submit"
                                                name="submit"
                                                type="submit"
                                                disabled={!(isValid && dirty)}
                                            >
                                                <span>Indienen</span>
                                            </SubmitButton>
                                        </div>
                                    </div>
                                </Form>
                            )}
                        </Formik>
                    )}
                </Mutation>
            </div>
        );
    }

    render() {
        const formState = this.state;
        const { errorList } = this.state;
        switch (formState.formStatus) {
        case 'submitted':
            return (
                <div className="form-alert alert-success">
                    Thank you for your Message.
                    <p>We will reply ASAP.</p>
                </div>
            );
        case 'loading':
            return <div className="form-alert alert-info">Please wait</div>;
        case 'error':
            return (
                <div className="form-alert alert-error">
                    An error has occurred.
                    {
                        errorList.map((error, index) => <p key={index}>{error}</p>)
                    }
                </div>
            );
        default:
            return this.form();
        }
    }
}
export default ContactForm;

Nu is onze contactformuliercomponent klaar en kunnen we deze importeren in de paginacomponent, voettekstcomponent of waar we maar willen.

Het is tijd om het WordPress-gedeelte aan te pakken.

In het bestand functions.php moeten we onze mutatie in het contactformulier registreren:


<?php function create_contact_form_mutation() { register_graphql_mutation( 'createContact', array( 'description' => 'Custom mutation creating new contact form submission',
            'inputFields'         => array(
                'email'   => array(
                    'type'        => 'String',
                    'description' => 'User email',
                ),
                'name'    => array(
                    'type'        => 'String',
                    'description' => 'User name',
                ),
                'phone'   => array(
                    'type'        => 'String',
                    'description' => 'User phone',
                ),
                'company' => array(
                    'type'        => 'String',
                    'description' => 'User company',
                ),
                'message' => array(
                    'type'        => 'String',
                    'description' => 'User message',
                ),
            ),
            'outputFields'        => array(
                'success' => array(
                    'type'        => 'Boolean',
                    'description' => 'Whether or not data was stored successfully',
                    'resolve'     => function( $payload, $args, $context, $info ) {
                        return isset( $payload['success'] ) ? $payload['success'] : null;
                    },
                ),
                'data'    => array(
                    'type'        => 'String',
                    'description' => 'Payload of submitted fields',
                    'resolve'     => function( $payload, $args, $context, $info ) {
                        return isset( $payload['data'] ) ? $payload['data'] : null;
                    },
                ),
            ),
            'mutateAndGetPayload' => function( $input, $context, $info ) {

                $sanitized_data = array();
                $errors = array();
                $success_data = array();
                $acceptable_fields = array(
                    'name',
                    'email',
                    'phone',
                    'company',
                    'message',
                );

                foreach ( $acceptable_fields as $field_key ) {
                    if ( ! empty( $input[ $field_key ] ) ) {
                        $sanitized_data[ $field_key ] = sanitize_text_field( $input[ $field_key ] );
                    } else {
                        $errors[] = $field_key . ' was not filled out.';
                    }
                }
                
                // ... Here we code what we want to do with the data we got.
                // Either we want to send an email to admin,
                // or create new custom post and save a message to database.


                $output = '';

                if ( ! empty( $errors ) ) {
                    $output = array(
                        'success' => false,
                        'data'    => wp_json_encode( $errors ),
                    );
                } else {
                    $output = array(
                        'success' => true,
                        'data'    => wp_json_encode( $success_data ),
                    );
                }

                return $output;

            },
        )
    );

}

add_action( 'graphql_register_types', 'create_contact_form_mutation' );

En dit is meer minder. Ons contactformulier is klaar.

Veel plezier met coderen!