Uniform and Ajax: the browser tries to download the json file

Hi, I’m having a strange issue working with Uniform plugin. I’ve seen it’s pretty used among the Kirby community, so, here I am…

I’m in this case (uniform and ajax): https://kirby-uniform.readthedocs.io/en/latest/examples/ajax/

The site is a single page application, so every page is loaded via ajax.

The issue: The first time the page where the form is embedded is loaded, everything is running fine. But when the whole page is reloaded via ajax, the submission of the form causes the browser to download the json file.

The form is inside a snippet, but I’m having the same issue when it’s in a template.

Any suggestion? Thanks!

Template

<form action="<?=page('ztest')->url()?>" method="POST">
        <h3><?=$mainTxt?></h3>
        <input name="email" class="uk-input uk-form-large col-black <?=$disabled?>" type="email" 
            autocomplete="off" placeholder="Email" value="<?=$arrUser['email']?>" />  

        <div class="uk-margin uk-grid-small uk-child-width-auto uk-grid">
            <label><input name="nl_1" class="uk-checkbox" type="checkbox" autocomplete="off" <?=$arrUser['nl_1']?> value="nl_1"/> Newsletter1</label>
            <label><input name="nl_2" class="uk-checkbox" type="checkbox" autocomplete="off" <?=$arrUser['nl_2']?> value="nl_2"/> Newsletter2</label>
            <label><input name="nl_3" class="uk-checkbox" type="checkbox" autocomplete="off" <?=$arrUser['nl_3']?> value="nl_3"/> Newsletter3</label>
            <label><input name="nl_4" class="uk-checkbox" type="checkbox" autocomplete="off" <?=$arrUser['nl_4']?> value="nl_4"/> Newsletter4</label>
            <label><input name="nl_5" class="uk-checkbox" type="checkbox" autocomplete="off" <?=$arrUser['nl_5']?> value="nl_5"/> Newsletter5</label>
        </div>

        <?php echo csrf_field() ?>
        <?php echo honeypot_field() ?>
        <input type="submit" value="<?=$btnLabel?>" class="uk-button uk-button-secondary">
        <p id="message"></p>
    </form>

Route

//UNIFORM -- Da mettere pagina definitiva in pattern
    //User manual: https://kirby-uniform.readthedocs.io/en/latest/examples/ajax/
    [
      'pattern' => 'ztest',
      'method' => 'POST',
      'action' => function () {
          $form = new \Uniform\Form([
              'email' => [
                  'rules' => ['required', 'email'],
                  'message' => 'Devi inserire una email valida!',
              ],
              'nl_1' => [],
              'nl_2' => [],
              'nl_3' => [],
              'nl_4' => [],
              'nl_5' => []
          ]);
  
          // Perform validation and execute guards.
          $form->withoutFlashing()
                ->withoutRedirect()
                ->guard();
  
          if (!$form->success()) {
              // Return validation errors.
              return Response::json($form->errors(), 400);
          }
  
          // If validation and guards passed, execute the action.
          feeData_saveUser($form);
  
          if (!$form->success()) {
              // This should not happen and is our fault.
              return Response::json($form->errors(), 500);
          }
  
          // Return code 200 on success.
          return Response::json([], 200);
      }
    ]

JS

<script>
    
    //Funzionamento client del form

    window.addEventListener('load', function () {
        var form = document.querySelector('form');
        var message = document.getElementById('message');
        var fields = {};
        form.querySelectorAll('[name]').forEach(function (field) {
            fields[field.name] = field;
    });

    // Displays all error messages and adds 'error' classes to the form fields with
    // failed validation.
    var handleError = function (response) {
        var errors = [];
        for (var key in response) {
            if (!response.hasOwnProperty(key)) continue;
            if (fields.hasOwnProperty(key)) fields[key].classList.add('error');
            Array.prototype.push.apply(errors, response[key]);
        }
        message.innerHTML = errors.join('<br>');
    }

    var onload = function (e) {
        if (e.target.status === 200) {
            message.innerHTML = 'Success!'
        } else {
            handleError(JSON.parse(e.target.response));
        }
    };

    var submit = function (e) {
        e.preventDefault();
        var request = new XMLHttpRequest();
        request.open('POST', e.target.action);
        request.onload = onload;
        request.send(new FormData(e.target));
        // Remove all 'error' classes of a possible previously failed validation.
        for (var key in fields) {
            if (!fields.hasOwnProperty(key)) continue;
            fields[key].classList.remove('error');
        }
    };
    form.addEventListener('submit', submit);
});
</script>

What json file is downloaded? And why would you reload the page?

The json file (ztest.json, where ztest is the page name) is empty. Don’t know if it can help, but here’s the header

About the “reload” thing: being a ajax based site (SPA), most of the pages are served via ajax. When this happens, I run into the above issue.

For what it’s worth, I also tried to use the GET method instead of the default POST one, but i run into the “The CSRF token was invalid” error.