Gatsby – WordPress: formulario de contacto

Gatsby – WordPress: formulario de contacto

Este artículo cubre uno de los métodos para crear un formulario de contacto en Gatsby.js, obteniendo los datos de la base de datos de WordPress a través de GraphQl.

Necesitará algunas habilidades de codificación en JS, React, PHP y algún conocimiento de las funciones de WordPress.

Las bibliotecas que se utilizarán aquí son:

reaccionar apolo
Formik
Reacción de interfaz de usuario semántica de Formik

Comencemos por instalar todas las bibliotecas mencionadas anteriormente.

En la terminal, abra la carpeta raíz de la instancia de Gatsby y luego

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

Para que nuestro formulario funcione, también tendremos que programarlo en Gatsby y WordPress. Empecemos por la parte de Gatsby.

En la carpeta raíz/src, cree una nueva subcarpeta. ¿Por qué no lo llamamos “mutaciones”. Luego creamos un nuevo archivo. Para mantener una lógica en nuestra convención de nomenclatura, lo llamamos 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;

Ahora podemos crear un componente de formulario de contacto. Para mantener una lógica en una estructura de archivos, creemos una nueva carpeta “Forma de contacto” en la carpeta raíz/componentes. Luego, necesitamos crear un nuevo archivo allí: ContactForm.js.

Aprovecharemos el estado React, la validación Yup y la funcionalidad Formik.


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;

Ahora nuestro componente de formulario de contacto está listo y podemos importarlo al componente de página, al componente de pie de página o donde sea que lo necesitemos.

Es hora de ocuparse de la parte de WordPress.

En el archivo functions.php necesitamos registrar la mutación de nuestro formulario de contacto:


<?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' );

Y esto es más menos. Nuestro formulario de contacto está listo.

¡Feliz codificación!