Emma Norrman

Add a contact form to your website using VUE and PyroCMS

Let's add a contact form using VUE and PyroCMS to your website. The data submitted will be validated both in the front and in the back end. It will also be saved to your database. Thanks to PyroCMS all the heavy lifting is already done for you!


Forms module

The quickest way of creating a contact form and store the data submitted is by using the forms module. To be able to use it, it has to be installed and we also need to install the standard form extension.

Create and setup the contact form

Once you have installed the forms module you are able to access a new link in your left side navigation called Forms. Once there, create a new form named Contact Us. The slug of this form will automatically be named contact_us.

Save it and go to the fields section where you simply create the fields you need your form to have. In our example we keep it simple by only adding an email field.

When the fields are created, go back to the form section and assign them to your form.

Once a form has been submitted, it will be possible to view the data from the entries link. To define what fields to be displayed in that list, you can go to options tab within your form and select them.

Save it, and you are done!

Since we are going to use ajax and not send any email notifications to anyone this is all the setup we need to do. But depending on your needs, you are able to set more options within the form

Create a vue component

We will be using vue to handle everything in the front end, so we must first create our component. Trying to keep this as simple as possible to make it easier to read.

Important! We are skipping handling of any response errors from the server. But in the real world, you should make sure you display errors that might come back from the server once Pyro has run it's validation rules on your fields.

   <div class="container">
       <form id="contact" v-on:submit.prevent="onSubmit" method="POST" :action="url">

           <div v-show="!showSuccessMessage">

                <!-- Handle error messages if the field is not validated -->
                <i v-show="errors.has('fields.email')"></i>
                <span v-show="errors.has('fields.email')">
                    {{ errors.first('fields.email') }}


                You could also use this method if you would like to collect all
                errors in one place 
            <div v-show="errors.any()">

                    Errors found!

                    <li v-show="errors.has('fields.email')">
                        {{ errors.first('fields.email') }}


            <!-- If the form was validated and successfully submitted show a message -->
            <div v-show="showSuccessMessage">
                <h2>Thank you!</h2>

            <!-- If there are any issues, show an error message -->
            <div v-show="showErrorMessage">
                <h2>Your message has not been submitted!</h2>

              <!-- We are hiding the button during submission -->
            <button v-show="!submitting" type="submit">Submit</button>



import axios from "axios";
import Vue from "vue";
import VeeValidate from "vee-validate";
export default {
    name: "contact-form",
    props: {
        url: {
            type: String,
            required: true
    data() {
        return {
            email: null,
            showSuccessMessage: false,
            showErrorMessage: false,
    methods: {
        onSubmit() {
            this.$validator.validateAll("fields").then(result => {  
                if (result) {

                    let myForm = document.getElementById("contact");
                    let formData = new FormData(myForm);

                        .post(this.url, formData)
                        .then(response => {
                            if (response.data.success === true) {
                                this.showSuccessMessage = true;
                                this.showErrorMessage = false;
                            } else {
                                  // Make sure you display the response errors which we are 
                                  // not doing in this example.
                                this.showErrorMessage = true;
                        .catch(e => {
                            this.showErrorMessage = true;

Display our form

To display our form, we have get our form as well as set the ajax option to true. This is how we do that:

{% set form = form('forms::contact_us').ajax(true).get() %}
<contact url='{{form.object.options.url}}'></contact>

These two lines can be added directly in your layout or other views you might have. You may also have an editor field type attached to your page, grid or block where you could add them. Possibilities are, as usual with Pyro, endless.