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
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';
In each of your modules/X.php
files, where X is the module name:
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]
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
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
})
}
})
}
}
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()
})
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!
Top comments (0)