I’m having trouble with getting AJAX form handling to work completely in modular pages.
I have a modular page /contact/modular.md, and several modules, including /contact/_contact-me/form.md
I understand that, since form 2.0, when using modular pages we can place the form frontmatter directly in the modular form.md. We don’t have to put the form in the modular.md that is “parent” to form.md.
However, when my /contact/_contact-me/form.md uses the code described in the docs to submit via AJAX (changing action: to point to /contact), the site does not display any message after submit, and I get a 500 Internal Server error in the browser Console for trying to access mysite.com/contact, even though that url is routable).
When I set things up the old way (form plugin < 2.0), and place the form frontmatter in /contact/modular.md, the problem vanishes: no 500 error, and the post-submit message displays.
Is it not possible to have AJAX form submission work correctly on a modular page, with the form contained in the module?
---
title: Contact Form
form:
name: contact
action: '/modular-page'
template: modular
refresh_prevention: true
fields:
name:
label: Name
placeholder: Enter your name
autocomplete: on
type: text
validate:
required: true
buttons:
submit:
type: submit
value: Submit
process:
save:
fileprefix: contact-
dateformat: Ymd-His-u
extension: txt
body: "{% include 'forms/data.txt.twig' %}"
message: Thank you for getting in touch!
---
# Contact form
Some sample page content
I’m also confused—my impression from the docs has been that we needed some html and js code like the below (from the example in the docs) in order for the same-page confirmation message to appear.
<div id="form-result"></div>
<script>
$(document).ready(function(){
var form = $('#ajax-test-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>
Did I misunderstand, or is this no longer the case and the functionality is built in to the form plugin now?
I was referring to your example in this post, which uses the html and js code. It also specifies that the form action goes to an empty pages/forms/ajax-test/form.md. I’m curious about the reasoning for that approach vs the simplicity of what you just shared. Is the earlier example no longer required?
@prw, Yes, the form is working, but not with Ajax… I forgot half the steps necessary and didn’t notice the form did a regular HTTP post… Sorry about the confusion.
---
title: Contact
form:
name: ajax-test-form
action: '/home'
template: form-messages
refresh_prevention: true
fields:
name:
label: Your Name
type: text
buttons:
submit:
type: submit
value: Submit
process:
message: 'Thank you for your submission!'
---
<div id="form-result"></div>
<script>
$(document).ready(function(){
var form = $('#ajax-test-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>
The Chrome debugger breaks at the success function of the Ajax request and the message is shown inside <div id="form-result"></div>. So it seems to be working in a modular page using Ajax.
Thank you for spending some time with this. I have a few questions:
I notice in your most recent version, there is no action: field in the frontmatter. Is that okay? Is that only necessary if wanting to use the action: '/forms/ajax-test'?
And also on the subject of the “dummy page” pages/forms/ajax-test/form.md: I had seen a few examples, including yours from that other thread I mentioned, that use this “dummy page” with a blank form. But when I look closer at the docs, I see that they are not using a dummy page. Instead pages/forms/ajax-test/form.md in their example is the actual page containing the form, so action: '/forms/ajax-test' refers not to a dummy but to the same page.
There is a note in that docs page on ajax form submission regarding dealing with redirects:
NOTE: We use a hard-coded action: '/forms/ajax-test' so the ajax has a consistent URL rather than the letting the form set the action to the current page route. This resolves an issue with the Ajax request not handling redirects properly. This can otherwise cause issues on the 'home' page. It doesn't have to be the current form page, it just needs to be a consistent, reachable route.
So I’m confused about this dummy page idea, and wondering when or why it would be useful, since the docs are talking about an action that points to the same page the form is on. Sorry, hope that makes my question clear.
@prw, You may be entirely right and I may be entirely wrong about the ‘dummy page’ and ‘action’… In hind side, I think I’m probably wrong. The mind plays funny games sometimes
How did my mind twist and turn back then?
When I tried to answer the earlier question about Ajax in a modular page, I had no experience with Forms (still don’t use them) and the docs were confusing me.
Especially the following two lines:
First, we’ll create a form in a page called: forms/ajax-test/ and create a form page called form.md.
Does the docs mean 1 page or 2 pages? Although not sure, I thought 2…
NOTE: We use a hard-coded action: '/forms/ajax-test' so the ajax has a consistent URL rather than the letting the form set the action to the current page route. […]
The above note lead me to think: “Ah, don’t point to the current page, but to the other. So the docs means two pages…”
NOTE: […] It doesn’t have to be the current form page, it just needs to be a consistent, reachable route.
Again I thought: “A second dummy page will do”
Also because why would you create a form below folder ‘/forms’ which doesn’t show up in the menu? Dummy to create a consistent URL perhaps?
So I created two forms:
/forms/ajax-test/form.md (the ‘dummy’ needed for the consistent URL?)
01.home/_contact/form.md with the Ajax form definition…
And guess what? It worked, so I must have done something right… I thought…
As I followed your initial examples, with the dummy page, the logic that you just outlined seemed clear. I understand where you were coming from! It was only after looking carefully at the docs that I started to have doubts. You’re right, they leave some ambiguity—what’s the purpose of the folder /forms, as you say? It would be good to have those questions cleared up for future readers.
I’m still a beginner, but I’m wondering if the use of the dummy page “worked” because the js prevented loading of the dummy page. I don’t know!
@prw, Still in doubt… In my explanation above, I’ve added another suggestive line from the docs that my hint to using a ‘dummy’ page:
NOTE: […] It doesn’t have to be the current form page, it just needs to be a consistent, reachable route.
Also, when using action: /home instead of action: /forms/ajax-test, could the form now run into: “This can otherwise cause issues on the ‘home’ page.” ? Because /home is often redirected to /.
You said:
[…] I’m wondering if the use of the dummy page “worked” because the js prevented loading of the dummy page. I don’t know!
No that’s not it.
Ajax has to be able to reach an existing route else the server will throw 404. For example: Using action: /existing-folder/default.md will do fine, but when using action: /non-existing-folder/default.md, Ajax will throw 404 in the console.
As said in the docs “it just needs to be a consistent, reachable route”.
That also hints why /forms/ajax-test/form.md can be an invisible (albeit empty) route.