Page refreshing after submit form

Hi! I’m building a website with a contact form modal on the footer of all pages. I’m using a shared controller ‘site.php’.

The form is working fine and I’m getting the emails. The problem is that after I click on submit, the page reloads and I need to scroll to the bottom to check if the message was sent or not.

How do I prevent page refresh?

Here’s the form code, inside ‘footer.php’ snippet:

<form action="<?php echo $page->url()?>/" method="POST">
	<div class="honeypot">
		 <label for="website">Website <abbr title="required">*</abbr></label>
		 <input type="url" id="website" name="website" tabindex="-1">
	</div>
	<!-- name -->
	<div class="contact--field" id="contactName">
		<input class="contact--input" type="text" id="name" name="name" placeholder="Name*" value="<?= esc($data['name'] ?? '', 'attr') ?>" required>
	</div>
	<!-- e-mail -->
	<div class="contact--field">
		<input class="contact--input" type="email" id="email" name="email" placeholder="E-mail*" value="<?= esc($data['email'] ?? '', 'attr') ?>" required>
	</div>
    <!-- message -->
	<div class="contact--field" id="contactTextarea">
		<textarea class="contact--input" id="text" name="text" placeholder="Nachricht" required><?= esc($data['text'] ?? '') ?></textarea>
	</div>
	<!-- terms -->
	<div class="contact--intro">
		<input type="checkbox" required>I have read and agree to the <a href="<?= $privacy->url() ?>" class="link-privacy">Privacy Policy</a>
	</div>
    <!-- submit button -->
	<input type="submit" name="submit" value="Submit" class="contact-submit button btn-white">
	<!-- alerts -->
	<?php if (isset($alert['name']) || isset($alert['email']) || isset($alert['text'])): ?>
		<div class="error">
			<?= isset($alert['name']) ? '<div class="alert-error">' . esc($alert['name']) . '</div>' : '' ?>
			<?= isset($alert['email']) ? '<div class="alert-error">' . esc($alert['email']) . '</div>' : '' ?>
			<?= isset($alert['text']) ? '<div class="alert-error">' . esc($alert['text']) . '</div>' : '' ?>
		</div>
	<?php endif ?>

	<!-- success -->
	<?php if($success): ?>
		<div class="alert-success">
			<p><?= $success ?></p>
		</div>
	<?php else: ?>
	<!-- error -->
	<?php if (isset($alert['error'])): ?>
		<div class="alert-success"><?= $alert['error'] ?></div>
	<?php endif ?>
</form>
<?php endif ?>

Here’s the ‘site.php’ controller:

<?php

return function($kirby, $pages, $page) {

    $kontakt = page('kontakt');
    $alert = null;

    if($kirby->request()->is('POST') && get('submit')) {

        // check the honeypot
        if(empty(get('website')) === false) {
            go($page->url());
            exit;
        }

        $data = [
            'name'  => get('name'),
            'email' => get('email'),
            'text'  => get('text')
        ];

        $rules = [
            'name'  => ['required', 'minLength' => 3],
            'email' => ['required', 'email'],
            'text'  => ['required', 'minLength' => 3, 'maxLength' => 3000],
        ];

        $messages = [
            'name'  => '*Please enter a valid name',
            'email' => '*Please enter a valid email address',
            'text'  => '*Please enter a text between 3 and 3000 characters'
        ];

        // some of the data is invalid
        if($invalid = invalid($data, $rules, $messages)) {
            $alert = $invalid;

            // the data is fine, let's send the email
        } else {
            try {
                $kirby->email([
                    'template' => 'email',
                    'from'     => esc($kontakt->from()), // The sender of the emails. This should be some address that is associated with the website
                    'replyTo'  => $data['email'],
                    'to'       => esc($kontakt->to()), // The email address that should be the receiver of the emails
                    'subject'  => esc($data['name']) . ' sent you a message from your contact form',
                    'data'     => [
                        'text'   => esc($data['text']),
                        'sender' => esc($data['name'])
                    ]
                ]);

            } catch (Exception $error) {
                if(option('debug')):
                    $alert['error'] = 'The form could not be sent: <strong>' . $error->getMessage() . '</strong>';
                else:
                    $alert['error'] = 'The form could not be sent!';
                endif;
            }

            // no exception occurred, let's send a success message
            if (empty($alert) === true) {
                $success = 'Vielen Dank für ihre Nachricht.';
                $data = [];
            }
        }
    }

    return [
        'alert'   => $alert,
        'data'    => $data ?? false,
        'success' => $success ?? false
    ];
};

Thank you!

You can’t prevent a page refresh when sending a form the standard way.

Instead, you could make an Ajax request to the server and then display the result in the page or redirect from there on success.

1 Like

Ok, but does $kirby->email() work with Ajax? Can you help me with the code?

Well, Ajax is client side JavaScript code that makes a request to the backend. So of course you cannot call $kirby->email() as PHP code directly in your JavaScript, but the whole purpose of Ajax is to be able to call a server side script.

I can help you with the code when and where you get stuck, but I cannot do the code for you. Maybe this Ajax recipe help: Load more with Ajax | Kirby CMS

It’s another use case, but the basics of these calls are always the same.

In the case of a form, you prevent default form submission and send the data with an Ajax post request to the form’s action attribute instead.

You can find code examples both with jQuery or vanilla JS on the web.