endernet.io

A Reusable Email Form Component

☕️ 5 min read

A Reusable Email Form Component

Here is an example of what we are going to build.

example 1

Prerequisites:

  • NPM/Yarn
  • Browserify or any other compiler
  • A Mailgun & EmailJS account (both free for testing)

Let’s start off with a boiler plate for our html.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />

    <title>Email Component</title>

    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <link rel="stylesheet" href="emailComponentStyle.css" />
  </head>
  <body>
    <div id="email_form"></div>

    <!-- Load React. -->
    <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
    <script
      src="https://unpkg.com/react@16/umd/react.development.js"
      crossorigin
    ></script>
    <script
      src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
      crossorigin
    ></script>
    <!-- Load our React component. -->
    <script src="email_form_bundle.js"></script>
  </body>
</html>

Now create a JavaScript file for the component, it should be named something other than what you are linking to in our <script /> tag.

When we use our compiler we will rename that compiled file, in my case “email_form_bundle.js”.

Assuming you have NPM already installed, run these commands to initialize React and install our necessary modules:

npm init -y
npm install emailjs-com

In our “email_form.js” file, lets start by creating our EmailForm class.

"use strict";

const e = React.createElement;

const emailjs = require("emailjs-com");

class EmailForm extends React.Component {
  render() {
    return React.createElement("div", null, "hello world!");
  }
}

const domContainer = document.querySelector("#email_form");
ReactDOM.render(e(EmailForm), domContainer);

From here in order to load any node modules with require() we need to compile our JavaScript file.

I’m going to use Browserify in this example, and I’ll also assume you have a compiler installed.

In your terminal, use this command to compile the file.

browserify email_form.js > email_form_bundle.js

Now if you reload your index.html file you should have a blank screen with “hello world!” at the top.

Let’s give our EmailForm class some state and create a form element to load onto the screen.

class EmailForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      message: "",
      errors: {
        email: "",
        message: ""
      },
      formValid: false,
      sent: false
    };
  }

  render() {
    return React.createElement(
      "div",
      null,
      React.createElement(
        "form",
        {
          className: "email-form",
          id: this.props.id,
          name: this.props.name,
          method: this.props.method,
          action: this.props.action
        },
        React.createElement("input", {
          className: "email-input",
          type: "email",
          name: "email",
          placeholder: "email",
          value: this.state.email,
          onChange: this.handleInputChange.bind(this),
          error: this.state.errors.email,
          required: true
        }),
        React.createElement("input", {
          className: "message-input",
          type: "textarea",
          id: "message",
          name: "message",
          placeholder: "message",
          value: this.state.message,
          onChange: this.handleInputChange.bind(this),
          error: this.state.errors.message,
          required: true
        }),
        React.createElement(
          "button",
          {
            className: "submit-button",
            onClick: null
          },
          "submit"
        )
      )
    );
  }
}

Time to create our event handlers, we’ll start with handling the input changes within the form inputs.

  // Just below our constructor

  handleInputChange(event) {
    event.preventDefault();
    const target = event.target;
    const name = target.name;
    const value = target.value;

    this.setState({ [name]: value, formValid: true });
  }

All this method does is take whatever input the user types into the input fields and sets the state of those objects.

Before we can create the next method to send our email, you will need to set up, if you haven’t already, an account with Mailgun and Emailjs.

First we will start with Mailgun. Once you’re logged in you will want to add your domain that you wish to use this component on.

example 2

Once you create the domain you will get simple instructions on how to add the DNS to your specific provider.

example 3
NOTE: These DNS records will be deleted once you see this.

Now on to EmailJS. Once you’re logged in you will need to add a new service.

example 4

It will ask you for an API key and a domain name. The API key can be found in the API Security tab under Settings of your Mailgun account.

example 5example 6

After you are finished creating the service we will need to create an Email Template.

example 7

Fill out the necessary fields and take note of your Template ID and User ID.

example 8example 9example 10

Now that the setup is finally complete we can move on to creating the method to send our message!

Back in your email_form.js, add this method:

// Right below handleInputChange()
sentMessage(event) {
  if (this.state.formValid) {
    event.preventDefault();

    const templateParams = {
      from_name: this.state.email,
      message_html: this.state.message
    };

    emailjs
      .send(
        "mailgun",
        "YOUR TEMPLATE ID GOES HERE",
        templateParams,
        "YOUR USER ID GOES HERE"
      )
      // This is just a response for testing, take out on deployment
      .then(response => {
        console.log("SUCCESS!", response.status, response.text);
      });

    this.setState({
      email: "",
      message: "",
      sent: true
    });
  } else {
    React.createElement("div", "Email not valid!");
  }
}

Now all that’s left to do is to call this method once we hit our Submit button. Where before we had onClick: null, instead call the sentMessage() method.

React.createElement(
  "button",
  {
    className: "submit-button",
    onClick: this.sentMessage.bind(this)
  },
  "submit"
);

We should also add a little validation at the beginning. So your render() should look something like this:

render() {
  if (this.state.sent) {
    return React.createElement(
      "div",
      {
        className: "email-success"
      },
      "email sent!"
    );
  }

  return React.createElement(
    "div",
    null,
    React.createElement(
      "form",
      {
        className: "email-form",
        id: this.props.id,
        name: this.props.name,
        method: this.props.method,
        action: this.props.action
      },
      React.createElement("input", {
        className: "email-input",
        type: "email",
        name: "email",
        placeholder: "email",
        value: this.state.email,
        onChange: this.handleInputChange.bind(this),
        error: this.state.errors.email,
        required: true
      }),
      React.createElement("input", {
        className: "message-input",
        type: "textarea",
        id: "message",
        name: "message",
        placeholder: "message",
        value: this.state.message,
        onChange: this.handleInputChange.bind(this),
        error: this.state.errors.message,
        required: true
      }),
      React.createElement(
        "button",
        {
          className: "submit-button",
          onClick: this.sentMessage.bind(this)
        },
        "submit"
      )
    )
  );
}

There you have it! A small React component that you can place anywhere in an html file.

NOTE: I recommend creating more validation depending on the amount of traffic your website will receive, this is just a basic form that is still susceptible to spam.