Ajax form validation on onepager

Hello there,

I am a Kirby newbie and don’t have much experience in neither PHP nor JS. However, I am building a onepage site using the cookbook recipe and it’s all fine so far. The page does have a contact form and I can validate the user input fine with PHP using the example from Github.

Since this is a onepager I want to give immediate feedback without leaving the form section so I am trying to enhance this using ajax. There is a nice recipe (that I vaguely understand) but I am running into problems to adapt it for my page.

I will try to explain my problem (please excuse me if it is a little clumsy, as mentioned I not very firm with PHP/JS). The server side validation works fine but I can’t get the ajax submission to work. The script from the recipe picks up the form url and the related JSON template (which is supposed to echo the user input) via

var url = form.attr(‘action’) + ‘.json’;

to use this in the ajax call. In my case this doesn’t yield anything useful, just “rootdirctory.json” and thus a 404 in the ajax call. So I tried to hardcode the URL of a JSON file which works for the call but returns “TypeError: response is null”. So I guess that the JSON template does not return anything because it is not in the place where it is supposed to be?

I hope some of you coding wizards out there can help me to sort this out.

Many thanks in advance!

Could you post the whole code of all the relevant files, please?

Allright, thanks for looking into this!

Here is my contact snippet:

 <!-- Contact Section -->

    <section id="contact" class="signup-section">
      <div class="container">
        <div class="row">
          <div class="col-md-10 col-lg-8 mx-auto text-center">

            <i class="far fa-paper-plane fa-2x mb-2 text-white"></i>
            <h2 class="text-white mb-5"><?= $sections->title()->kirbytext() ?></h2>

            <form id="contactform" action="<?= $page->url() ?>" method="post">
            <input type="text" class="form-control form-control-sm my-input" name="name" id="name" placeholder="Your name">
            <input type="email" class="form-control form-control-sm my-input" name="email" id="email" placeholder="Your email address" >
            <textarea rows="4" cols="20" class="form-control form-control-sm my-input" name="message" id="message" ">Your message...</textarea> 
            <input type="submit" name="submit" value="Submit" class="btn btn-primary mx-auto">
            <button class="btn btn-primary mx-auto" type="submit" name="submit" value="Register" </button>Register</button>
            <div class="honey">
     		<label for="website">If you are a human, leave this field empty</label>
     		<input type="website" name="website" id="website">

    <!-- Contact Section -->
    <section class="contact-section bg-black">
      <div class="container">

        <div class="social d-flex justify-content-center">
          <a href="#" class="mx-2 text-white">
            <i class="fab fa-soundcloud"></i>
          <a href="#" class="mx-2 text-white">
            <i class="fab fa-facebook-f"></i>
          <a href="#" class="mx-2 text-white">
            <i class="fas fa-envelope"></i>

Here is the JS:

$('#contactform').on('submit', function(e) {
  // clear alerts
  // define some variables
  var form = $(this);
  var url  = form.attr('action') + '.json';
  //var url  = 'index.json.php';
  //var url = $('#contactform').prop('action') + '.json';
  var data = form.serialize();

    type: 'POST',
    dataType: 'json',
    url: url,
    data: data,
    // if the ajax call is successful ...
    success: function(response) {
      // in case form validation has errors
      if(response.errors) { //<--- that's where it fails
		console.log("response errors");
        // loop through errors array
        $.each(response.errors, function(key, message) {
          // find the alert box for each input field
          var element = form.find('#' + key).next();

          // add the error message to the field

      // if registration was successful
      if(response.success) {
        element = $('.message');

        // show success message and hide form

      // if registration failed
      if(response.error) {
        element = $('.message');

        // show error message
    error: function (xhr, ajaxOptions, thrownError) {

And this is the JSON template:

echo json_encode($response, ARRAY_FILTER_USE_KEY);

It’s probably a problem with the URL, try

 var url  = form.attr('action') + '/.json';

Hello, thanks for your help!

This doesn’t result in a vaild URL, so I get 500.

What is the URL supposed to be?


What is your json representation called, home.json.php? The URL looks like it should look, provided there is a valid json representation

Yes, it is home.json.php and it lives in the templates directory next to home.php.

And the controller and the validateForm() function are also all in place? If you can’t get it to work, you can send me a link to a zipped version of your project and I can look into it tonight.

The controller is there (home.php in controllers), and the validateForm.php also (in Plugins). I changed the controller code to the original from the recipe and now I get 200 ok and:

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

So it seems it is something wrong with the JSON that comes back. What structure is it supposed to have? Sorry, I don’t fully understand the way the these bits work together.

If I can’t get it to work I will send you the code.


Hello, thanks for your help, I got it working.


@allquiet Great! Would you tell us what the problem was and how you solved it? Might be useful for others trying to achieve the same?

It was a combination of wrong URL for the ajax call, incorrect return values from the controller and mistakes in JS to process the return values.