Can't make AJAX call execute in a simple contact form

Hi there!
Having difficulties to run form with an AJAX.
I’m missing something…
I’ve Modular Page, called contact
In Frontmatter I’ve this code:

title: 'Contact Us'
body_classes: 'modular header-lite fullwidth'
menu: Contacts
onpage_menu: false
cache_enable: false
form:
    name: my-nice-form
    action: /contact
    template: form-messages
    refresh_prevention: true
    fields:
        -
            name: name
            id: name
            label: Name
            classes: 'form-control form-control-lg'
            placeholder: 'Enter your name'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: email
            id: email
            classes: 'form-control form-control-lg'
            label: Email
            placeholder: 'Enter your email address'
            type: email
            validate:
                rule: email
                required: true
        -
            name: message
            label: Message
            classes: 'form-control form-control-lg'
            size: long
            placeholder: 'Enter your message'
            type: textarea
            validate:
                required: true
    buttons:
        -
            type: submit
            value: Submit
            classes: 'btn btn-primary btn-block'
    process:
        -
            email:
                from: '{{ config.plugins.email.from }}'
                to:
                    - '{{ config.plugins.email.from }}'
                    - '{{ form.value.email }}'
                subject: '[Feedback] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
        -
            save:
                fileprefix: feedback-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
        -
            message: 'Thank you for your feedback!'
        -
            display: thankyou
content:
    items: '@self.modular'
    order:
        by: default
        dir: asc

And in the editor:

<script>
$(document).ready(function(){

    var form = $('#my-nice-form');
    form.submit(function(e) {
        // prevent form submission
        e.preventDefault();

        // submit the form via Ajax
        $.ajax({
            url: form.attr('action'),
            type: form.attr('method'),
            dataType: 'html',
            data: form.serialize(),
            success: function(result) {
                // Inject the result in the HTML
                $('#form-result').html(result);
            }
        });
    });
});
</script>

So, the whole modular.md have mentioned code from above.

Once I submit form without AJAX - the thank you message appears, but with AJAX - I see empty HTML markup with plain email link.

Thanks in advance!

@01K, I’m not a form user, but did some digging for you…

A few chapters in the documentation are of interest:

After a bit of reading and sorting out some confusion from the docs, I created the following in a One-Page skeleton:

  1. Created a new Contact page as a child page of the modular

  2. Created an empty file ‘/user/pages/forms/ajax-test/form.md’.
    See the documentation on Ajax Submission for an explanation.

    The filestructure is now:

    /user/pages/
      01.home/
        01._hero/
        02._highlights/
        03._callout/
        04._features/
        05._contact/     <-- new folder
           form.md       <-- new page with form definition
        modular.md
      forms/             <-- new folder
         ajax-test/      <-- new folder
            form.md      <-- new empty page
    
    
  3. I copied your code into ‘05._contact/form.md’ and made some changes to reflect the documentation. See the inline comments.

    ---
    title: 'Contact Us'
    body_classes: 'modular header-lite fullwidth'
    menu: Contacts
    # onpage_menu: false       # <-- this belongs to main modular page
    cache_enable: false
    form:
       name: my-nice-form
       # action: /contact            # <-- see docs about Ajax
       action: /forms/ajax-test      # <-- see docs about Ajax
       template: form-messages
       refresh_prevention: true
       fields:
          -
             name: name
             id: name
             label: Name
             classes: 'form-control form-control-lg'
             placeholder: 'Enter your name'
             autocomplete: 'on'
             type: text
             validate:
                required: true
          -
             name: email
             id: email
             classes: 'form-control form-control-lg'
             label: Email
             placeholder: 'Enter your email address'
             type: email
             validate:
                rule: email
                required: true
          -
             name: message
             label: Message
             classes: 'form-control form-control-lg'
             size: long
             placeholder: 'Enter your message'
             type: textarea
             validate:
                required: true
       buttons:
          -
             type: submit
             value: Submit
             classes: 'btn btn-primary btn-block'
       process:
          -
             email:
                from: '{{ config.plugins.email.from }}'
                to:
                   - '{{ config.plugins.email.from }}'
                   - '{{ form.value.email }}'
                subject: '[Feedback] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
          -
             save:
                fileprefix: feedback-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
          -
             message: 'Thank you for your feedback!'
          # -                     <-- This action will route the user to a 'thankyou' page
          #    display: thankyou  <-- You don't want that when using Ajax
    # content:       <-- content definition belongs to main modular page
    #    items: '@self.modular'
    #    order:
    #       by: default
    #       dir: asc
    ---
    <div id="form-result"></div>       <!-- required to display result of submit -->
    
    <script>
    $(document).ready(function(){
    
       var form = $('#my-nice-form');
       form.submit(function(e) {
          // prevent form submission
          e.preventDefault();
    
          // submit the form via Ajax
          $.ajax({
                url: form.attr('action'),
                type: form.attr('method'),
                dataType: 'html',
                data: form.serialize(),
                success: function(result) {
                   // Inject the result in the HTML
                   $('#form-result').html(result);
                },
                // The following is added for debugging purposes.
                error: function(result) {
                   // Inject the result in the HTML
                   $('#form-result').html(result.responseText);
                }
          });
       });
    });
    </script>
    

You should now have a contact form in a modular child page, that submits the form using Ajax…

1 Like

Thank you very much @pamtbaau!
I hope I will finish it.
The display template should be Form?

@01K, Not sure what you mean with your display template remark…

As you can see in the folder structure, the names of the files are ‘form.md’. This already tells Grav that the template to be used is the ‘form’ template. No need to set that again in the frontmatter of a page.

Or do you perhaps using the Admin plugin to create a page? I that case, I have no idea since I don’t use it… Took a look at it a minute ago, but wasn’t able to create a child modular page. Nor did I find a how-to in the documentation…

Maybe someone else know how to do this using the Admin plugin?

Yeah, I’m using the admin panel.
That’s how does it look like:

@01K, It seems to me, according the screenshot you are showing, you are not creating a child page of a modular page, but instead a root page with template ‘Form’.

user/pages/
   05.contact/
      form.md

When you use ‘+Add v / Add Modular’, to add a new child page to a modular page, you will get a different dialog. In that dialog, you won’t see template ‘Form’ but only a list of templates available in: /user/themes/quark/templates/modular which are ‘Features’, ‘Hero’, ‘Text’ (for Quark that is)

ah, the deeper I go, the less I understand :frowning:
Please, could you attach it as a archive, in such way I could undestand the structure and logic from admin panel, how it does look like

@01K That holds for just about everything in life…

ah, the deeper I go, the less I understand

If you allow me to give some unsolicited advise:

  • Start reading the documentation page-by-page, starting with Basic. And try the samples…
  • Also, to get a better feel of the basics of Grav, use an editor instead of Admin to create folders and pages, edit frontmatter, Twig templates etc.
    I personally use the popular and free Visual Studio Code, which understands Markdown, PHP, Twig etc.

I’m getting towrds the result, I’m think so… but now the browser stops responding, once I run this page.
It seems it goes to infinite loop.

The structure, which I’ve now:

-pages
	01.home
	02.about
	xxx
	
	05.contacts
		_form
		_main
		thankyou
	modular.md
	
	error
	forms
		ajax-form
		form.md <-empty file

modular.md from 05.contacts folder features this code:

---
title: Contacts
content:
    items: '@self.modular'
    order:
        by: default
        dir: asc
body_classes: 'modular header-image fullwidth contacts'
menu: Contacts
onpage_menu: false
process:
    markdown: true
    twig: true
---

form.md from 05.contacts-> _form have this code:

---
body_classes: 'modular header-lite fullwidth'
cache_enable: false
form:
    name: my-nice-form
    action: /forms/ajax-form
    template: form-messages
    refresh_prevention: true
    fields:
        -
            name: name
            id: name
            label: Name
            classes: 'form-control form-control-lg'
            placeholder: 'Enter your name'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: email
            id: email
            classes: 'form-control form-control-lg'
            label: Email
            placeholder: 'Enter your email address'
            type: email
            validate:
                rule: email
                required: true
        -
            name: message
            label: Message
            classes: 'form-control form-control-lg'
            size: long
            placeholder: 'Enter your message'
            type: textarea
            validate:
                required: true
    buttons:
        -
            type: submit
            value: Submit
            classes: 'btn btn-primary btn-block'
    process:
        -
            email:
                from: '{{ config.plugins.email.from }}'
                to:
                    - '{{ config.plugins.email.from }}'
                    - '{{ form.value.email }}'
                subject: '[Feedback] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
        -
            save:
                fileprefix: feedback-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
        -
            message: 'Thank you for your feedback!'
---

<div id="form-result"></div>

<script>
$(document).ready(function(){

   var form = $('#my-nice-form');
   form.submit(function(e) {
      
      e.preventDefault();
      
      $.ajax({
            url: form.attr('action'),
            type: form.attr('method'),
            dataType: 'html',
            data: form.serialize(),
            success: function(result) {
               
               $('#form-result').html(result);
            },
            // The following is added for debugging purposes.
            error: function(result) {
               
               $('#form-result').html(result.responseText);
            }
      });
   });
});
</script>		

I’ve got blank screen with no output. It should work, but…

@01K The contents you have given for the modular.md and form.md, are working fine.

Your folder structure looks wrong though. This is mine:

/pages/
  01.home/
  02.typography/
  03.contacts
     _main/
        text.md
     _form/
        form.md
     modular.md
  forms/
     ajax-form/
        form.md

Few questions/remarks:

  • The following setting in modular.md doesn’t seem useful, because the modular itself usually doesn’t contain any text apart from the frontmatter.
    process:
      markdown: true
      twig: true
    
  • What is your rationale for using a modular page instead of a regular page for a contact form? The following is a simple contact form using a regular page:
    Folder structure:
    /pages/
       ...
       04.simple-contact
          form.md
       forms/
          ajax-form/
             form.md
    
    Content of ‘/pages/04.simple-contact/form.md’:
    ---
    body_classes: 'modular header-lite fullwidth'
    cache_enable: false
    form:
        name: my-nice-form
        ... etc.
    ---
    # Contact Us
    
    If you want to contact us, please use our contactform
    
    <div id="form-result"></div>
    
    <script>
    $(document).ready(function(){
    
       var form = $('#my-nice-form');
       form.submit(function(e) {
    
          e.preventDefault();
    
          $.ajax({
                url: form.attr('action'),
                type: form.attr('method'),
                dataType: 'html',
                data: form.serialize(),
                success: function(result) {
    
                   $('#form-result').html(result);
                },
                / / The following is added for debugging purposes.
                error: function(result) {
    
                   $('#form-result').html(result.responseText);
                }
          });
       });
    });
    </script>
    

Hi!
Hm, very strange.
I’ve tried already numerous times, and all possible combinations, but I got an infinite loop on my server, just a blank screen. No any output or error messages.
Could you please check the file with form from my website?
https://kuzma.lt/js/05.contact.zip
I put it in pages/folder
And in pages/ I’ve got
forms/ajax-form/form.md empty file
I don’t have any ideas about why it doesn’t work…

@01K, It works fine…

Suggestions:

  • Did you play with routes anywhere?
  • Did you alter .htaccess?
  • Whatever the answer above… Create a fresh installation and delete the new /pages/ folder and copy your pages folder from your current site.
  • NB. Drop the `/thankyou’ folder, because the form is using Ajax and doesn’t route to the thankyou page.
1 Like

I think, you gave the right suggestion, the .htaccess
It is standard, only featuring RewriteEngine On

@01K, I’m afraid I don’t understand you reply…

If .htaccess is untouched, there should be a lot more going on than RewriteEngine On

Please download Grav, create a fresh installation and copy the /pages/ folder from your current site. See what happens…

1 Like

Brilliant,
from previous tutorial I’had left the tmpl override in templates/modular folder, so this caused the infinite loop :slight_smile:

@01K

Brilliant

Is that meant to be sarcastic towards your own ‘mishap’, or a compliment about my help? Or maybe both…

Last suggestion: Use Git in your project! That way you can see the changes you’ve made in a heartbeat and undo when finished ‘playing’ around…

1 Like

Thank you! Your suggestions helped me a lot!

Just commenting for future readers: creating a /pages/forms/ajax-test folder with a blank form.md file in it may not be necessary. See the discussion in this thread.