DEV Community

Elliott W
Elliott W

Posted on • Updated on

How to use Material Web Components with Contact Form 7

Goal

Replace the default fields that Contact Form 7 (CF7) outputs with our desired Material Web Component (MWC) components.

Requirements

A module bundler such as webpack or rollup.

Method

In your plugin or theme, create the following folder structure:

mwc
├── mwc.php
├── mwc.js
├── _mwc.scss
└── modules
    ├── text.php
    └── textarea.php
Enter fullscreen mode Exit fullscreen mode

You should copy any modules you want from wp-content/plugins/contact-form-7/modules. Here I've just used text and textarea.

As early as possible in the wordpress lifecycle require your mwc/mwc.php file. Then in the file, require all your modules like so:

require_once __DIR__ . '/modules/text.php';
require_once __DIR__ . '/modules/textarea.php';
Enter fullscreen mode Exit fullscreen mode

In each of your modules/X.php files, where X is the module name:

  1. Delete everything after the wpcf7_X_form_tag_handler function (we don't need to change validation or the tag generator menu)

Step Search for Replace with
1 wpcf7_add_form_tag_X mwc_wpcf7_add_form_tag_X
2 wpcf7_X_form_tag_handler mwc_wpcf7_X_form_tag_handler
3 $atts['placeholder'] = $value; $atts['label'] = $value;
4 input mwc-textfield (or whatever your component is)
5 %3$s <input type="hidden" name="' . $tag->name . '" />%3$s

3. At the top of the file add:

remove_action('wpcf7_init', 'wpcf7_add_form_tag_X');

At this point we should be able to make a CF7 template such as:

[text* full-name placeholder "Your Name"]
[email* email placeholder "Email address"]
[tel phone placeholder "Contact number (optional)"]
[textarea* message x4 placeholder "Your message"]
[submit "Submit]
Enter fullscreen mode Exit fullscreen mode

However the fields won't be rendering because we haven't imported the web components yet. To fix that, install your desired components:

npm install @material/mwc-textfield
npm install @material/mwc-textarea
Enter fullscreen mode Exit fullscreen mode

And then in your mwc/mwc.js file, add:

import '@material/mwc-textfield'
import '@material/mwc-textarea'

export default () => {
  const form = document.querySelector('.wpcf7-form')
  if (form) {
    form.querySelectorAll('.wpcf7-form-control-wrap').forEach(formControlWrap => {
      const formControl = formControlWrap.querySelector('.wpcf7-form-control')
      // If is web component
      if (formControl.tagName.includes('-')) {
        const input = formControlWrap.querySelector('input[type="hidden"]')
        // Make sure the hidden input value stays in sync with the mwc value
        formControl.addEventListener('change', () => {
          input.value = formControl.value
        })
      }
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

The reason we've had to add an extra hidden input and keep its value in sync with our mwc component value is because currently there is no support for web components to submit their values in forms. This is a very hacky solution, but does the job.

Now in your index.js file:

import MWC from 'mwc/mwc'

document.addEventListener("DOMContentLoaded", () => {
  MWC()
})
Enter fullscreen mode Exit fullscreen mode

And you should have working Material Web Components with Contact Form 7! :D

If you want to style your components, see the themeing guide.

Unfortunately I haven't tested this on other mwc components, so please let us know in the comments what other components you implemented and any gotchas that you had to work around.

Enjoy!

Discussion (0)