Getting started with AJAX forms

Silverstripe Version:
4.5.1

Question:
I’m looking to build a contact form which submits the content through ajax. I’ve not done this before using SilverStripe.

I’ve had a look at the tutorial on general ajax loading, but not sure how to tie this in with form submission.

Is anyone aware of a tutorial on this, or can offer general advice on where to start, please?

Thanks in advance!

Hopefully this will get you pointed in the right direction. This is what I generally recycle for my contact forms. I add this to PageController.php so I can add a contact form on any page.

public function ContactForm() { 
Requirements::javascript('themes/yourtheme/javascript/jquery/jquery-3.3.1.min.js');
    Requirements::javascript('themes/yourtheme/javascript/ajax.js');
	
    $fields = new FieldList( 
        TextField::create('FirstName'), 
        TextField::create('LastName'), 
        EmailField::create('Email'), 
        TextField::create('Phone'), 
        TextareaField::create('Message'),
		NocaptchaField::create('Captcha')
    ); 
    $actions = new FieldList( 
        FormAction::create('doSubmission', 'Submit')
    ); 
$validator = new RequiredFields('FirstName', 'LastName', 'Email', 'Message');
$form = new Form($this, 'ContactForm', $fields, $actions, $validator); 
$form->AddExtraClass('js-ajax-form');

// Load the form with previously sent data
$request = Controller::curr()->getRequest();
$session = $request->getSession();
if(is_array($session->get('ContactFormData'))) {
//	$form->sessionMessage('There was a problem submitting the form. Please review the errors below and try again.','error');
	$previous_data = $session->get("ContactFormData");
	$session->clear("ContactFormData");
	$form->loadDataFrom($previous_data);
} 
return $form;
		
}

public function doSubmission($data, $form) {
		
		$form->clearMessage();
		
		$siteconfig = SiteConfig::current_site_config();
        $email = new Email(); 

        $email->setTo($siteconfig->AdministratorEmail);  //replace this with To Email
        $email->setFrom($siteconfig->AdministratorEmail); 
        if($data['Email']) {
			$email->setReplyTo($data['Email']); 
		} 
        $email->setSubject("New Enquiry from Website : Contact Message from " . $data["FirstName"] . " " . $data["LastName"] ); 
        $messageBody = " 
            <p><strong>Name:</strong> {$data['FirstName']} {$data['LastName']}</p> 
            <p><strong>Email:</strong> {$data['Email']}</p> 
            <p><strong>Phone:</strong> {$data['Phone']}</p> 
            <p><strong>Message:</strong> {$data['Message']}</p> 
            <p><strong>IP Address:</strong> ". $_SERVER['REMOTE_ADDR'] . "</p> 
            <p><strong>Page URL:</strong> ". $this->AbsoluteLink() . "</p> 
        "; 
        $email->setBody($messageBody); 
        $email->send(); 
		
		

		$this->redirect($this->Link("success"));

}

ajax.js

$(function(){
var frm = $('form.js-ajax-form');

frm.submit(function (e) {	
    var $form = $(this);
    var formData = $form.serialize();
    var formAction = $form.prop('action');
    var formMethod = $form.prop('method');
    var encType = $form.prop('enctype');
	
    e.preventDefault();

    $.ajax({
		beforeSend: function(jqXHR,settings) {
            if ($form.prop('isSending')) {
                return false;
            }
            $form.prop('isSending',true);
			$form.addClass('uk-loading');
        },
        complete: function(jqXHR,textStatus) {
            $form.prop('isSending',false);
			$form.removeClass('uk-loading');
        },
        contentType: encType,
        data: formData,
        error: function(jqXHR, textStatus, errorThrown) {
            console.log('An error occurred.');
            window.location = window.location;
        },
		success: function(data, textStatus, jqXHR) {
            var $holder = $form.parent();
            $holder.fadeOut('normal',function() {
                $holder.html(data).fadeIn();
            });
        },
        type: formMethod,
        url: formAction
		
    });
});

});

1 Like

Thanks @Jellygnite - That’s really helpful!

I’ve adapted this to make it suitable for the site I’m working on, and it works a treat.

Have a great weekend!

This won’t work for forms with multiple submit options as it doesn’t include the action in the post body. If anyone needs multiple submit options, replace

var formData = $form.serialize();

with

var formData = $form.serializeArray();
formData.push({name: e.originalEvent.submitter.name, value: e.originalEvent.submitter.value});
1 Like