13

I looked all over and all I could find was about jQuery.

With much help from the great minds here at SO I've finally got my form validating (it's only client side right now, but that because it's an assignment). I need to now submit the form to a PHP file using AJAX.

My requirements are to verify that it was called via AJAX, verify all required fields have values and return a success status including the server time it was processed.

JSfiddle

The form action is empty right now for testing but will eventually call form.php with the code below.

HTML

<form id="contact" name="contact" onsubmit="return validateFormOnSubmit(this)" action="" method="post">
    <div>
        <label>First Name</label>
        <input placeholder="First Name" type="text" name="name" id="name" tabindex="1" autofocus />
        <div id="name-error" class="error"></div>
    </div>
    <div>
        <label>Nickname</label>
        <input placeholder="Nickname" type="text" name="nickname" id="nickname" tabindex="2" autofocus />
    </div>
    <div>
        <label>Email</label>
        <input placeholder="Email" type="email" name="email" id="email" tabindex="3" autofocus />
        <div id="email-error" class="error"></div>
    </div>
    <div>
        <label>Phone</label>
        <input placeholder="Phone" type="tel" name="phone" id="phone" tabindex="4" autofocus />
        <div id="phone-error" class="error"></div>
    </div>
    <div>
        <label>I prefer</label>
        <input type="radio" name="pet" id="Dogs" tabindex="5" autofocus />Dogs
        <input type="radio" name="pet" id="Cats" tabindex="6" autofocus />Cats
        <input type="radio" name="pet" id="Neither" tabindex="7" autofocus />Neither
        <div id="pet-error" class="error"></div>
    </div>
    <div>
        <label>My favorite number between 1 and 50</label>
        <input placeholder="Favorite number between 1 and 50" type="text" name="number" id="number" tabindex="8" autofocus />
        <div id="number-error" class="error"></div>
    </div>
    <div>
        <label>Disclaimer</label>
        <input type="checkbox" name="disclaimer" id="disclaimer" tabindex="9" autofocus />I confirm that all the above information is true.
        <div id="disclaimer-error" class="error"></div>
    </div>
    <div>
        <button type="submit" name="submit" id="submit" tabindex="10">Send</button>
    </div>
</form>

JS

function validateFormOnSubmit(contact) {
    reason = "";
    reason += validateName(contact.name);
    reason += validateEmail(contact.email);
    reason += validatePhone(contact.phone);
    reason += validatePet(contact.pet);
    reason += validateNumber(contact.number);
    reason += validateDisclaimer(contact.disclaimer);

    console.log(reason);
    if (reason.length > 0) {

        return false;
    } else {
        return false;
    }
}

// validate required fields
function validateName(name) {
    var error = "";

    if (name.value.length == 0) {
        name.style.background = 'Red';
        document.getElementById('name-error').innerHTML = "The required field has not been filled in";
        var error = "1";
    } else {
        name.style.background = 'White';
        document.getElementById('name-error').innerHTML = '';
    }
    return error;
}

// validate email as required field and format
function trim(s) {
    return s.replace(/^\s+|\s+$/, '');
}

function validateEmail(email) {
    var error = "";
    var temail = trim(email.value); // value of field with whitespace trimmed off
    var emailFilter = /^[^@]+@[^@.]+\.[^@]*\w\w$/;
    var illegalChars = /[\(\)\<\>\,\;\:\\\"\[\]]/;

    if (email.value == "") {
        email.style.background = 'Red';
        document.getElementById('email-error').innerHTML = "Please enter an email address.";
        var error = "2";
    } else if (!emailFilter.test(temail)) { //test email for illegal characters
        email.style.background = 'Red';
        document.getElementById('email-error').innerHTML = "Please enter a valid email address.";
        var error = "3";
    } else if (email.value.match(illegalChars)) {
        email.style.background = 'Red';
        var error = "4";
        document.getElementById('email-error').innerHTML = "Email contains invalid characters.";
    } else {
        email.style.background = 'White';
        document.getElementById('email-error').innerHTML = '';
    }
    return error;
}

// validate phone for required and format
function validatePhone(phone) {
    var error = "";
    var stripped = phone.value.replace(/[\(\)\.\-\ ]/g, '');

    if (phone.value == "") {
        document.getElementById('phone-error').innerHTML = "Please enter a phone number";
        phone.style.background = 'Red';
        var error = '6';
    } else if (isNaN(parseInt(stripped))) {
        var error = "5";
        document.getElementById('phone-error').innerHTML = "The phone number contains illegal characters.";
        phone.style.background = 'Red';
    } else if (stripped.length < 10) {
        var error = "6";
        document.getElementById('phone-error').innerHTML = "The phone number is too short.";
        phone.style.background = 'Red';
    } else {
        phone.style.background = 'White';
        document.getElementById('phone-error').innerHTML = '';
    }
    return error;
}

function validatePet(pet) {
    if ((contact.pet[0].checked == false) && (contact.pet[1].checked == false) && (contact.pet[2].checked == false)) {
        document.getElementById('pet-error').innerHTML = "Pet required";
        var error = "2";
    } else {
        document.getElementById('pet-error').innerHTML = '';
    }
    return error;
}

function validateNumber(number) {
    var num = document.forms["contact"]["number"];
    var y = num.value;
    if (!isNaN(y)) {

        //alert('va');

        if (y < 0 || y > 50) {
            //Wrong
            number.style.background = 'Red';
            document.getElementById("number-error").innerHTML = "Must be between 0 and 50.";
            var error = "10";
        } else {
            //Correct
            number.style.background = 'White';
            document.getElementById("number-error").innerHTML = "";
        }
        return error;
    } else {
        document.getElementById("number-error").innerHTML = "Must be a number.";
        var error = "3";
    }
    return error;
}

function validateDisclaimer(disclaimer) {
    var error = "";

    if (document.getElementById("disclaimer").checked === false) {
        document.getElementById('disclaimer-error').innerHTML = "Required";
        var error = "4";
    } else {
        document.getElementById('disclaimer-error').innerHTML = '';
    }
    return error;
}

PHP

<?php
$name = $_POST['name'];
$email = $_POST['email'];
$from = 'From: TangledDemo'; 
$to = 'myemail@domain.com'; 
$subject = 'Hello';
$message = "This is a message.";

if ($_POST['submit']) {              
    if (mail ($to, $subject, $message)) { 
        echo '<p>Your message has been sent!</p>';
} else { 
    echo '<p>Something went wrong, go back and try again!</p>'; 
} 
}
?>

thanks!

justinae
  • 387
  • 1
  • 2
  • 14

3 Answers3

21

Here is how you can submit your form via Ajax:

function submitFormAjax() {
    let xmlhttp= window.XMLHttpRequest ?
        new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.onreadystatechange = function() {
        if (this.readyState === 4 && this.status === 200)
            alert(this.responseText); // Here is the response
    }

    let name = document.getElementById('name').innerHTML;
    let email = document.getElementById('email').innerHTML;

    xmlhttp.open("GET","your_url.php?name=" + name + "&email=" + email, true);
    xmlhttp.send();
}

This example is using GET, but you could also use POST:

xmlhttp.open("POST","your_url.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("name=" + name + "&email=" + email);

Note:

You must call submitFormAjax() after validateFormOnSubmit is done with no errors, here:

if (reason.length == 0) {
    // Show some loading image and submit form
    submitFormAjax();
} else {
    return false;
}
John R Perry
  • 3,916
  • 2
  • 38
  • 62
António Almeida
  • 9,620
  • 8
  • 59
  • 66
  • 1
    Ok @BillyMathews! Didn't know that ... I've removed the reference :) – António Almeida Feb 19 '14 at 16:16
  • 1
    @ToniAlmeida thanks for that. I will start testing it now. Do I need to add 'var name = document.getElementById('name').innerHTML;' for each of the fields I want to submit or only the required ones? So is the jist of what's happening here is that ValidateForm runs first, gets all the errors out of the way, then submitForAjax runs and basically submits the whole form to form.php without having to refresh the page? I'm still wrapping my head around AJAX. **BillyMathews** I had no idea about W3schools. Thanks for the heads up. – justinae Feb 19 '14 at 16:24
  • Where can I test AJAX or do I have to do that on my live server? – justinae Feb 19 '14 at 16:28
  • @justinae, that's right, first you validate everything, then, you submit the form with all the needed parameters! And AJAX allows you to do this without refreshing the page! – António Almeida Feb 19 '14 at 16:37
  • You can test an AJAX request on your local machine, but, you need to request your `form.php`, so you need to have php on your local machine, otherwise test it on your live server. – António Almeida Feb 19 '14 at 16:39
  • Thanks @ToniAlmeida Here is my test environment: http://first_books.justineuteneier.com/contact.php Where do I put the name of my form, which is "contact"? – justinae Feb 19 '14 at 16:47
  • 1
    You don't need to, just add each of you values as parameters of get `xmlhttp.open("GET" ...` (Unless you have multiple forms in your page, do you?) – António Almeida Feb 19 '14 at 16:52
  • No, only one form. So in my case it would be 'xmlhttp.open("GET","form.php?name=" + name + "&email=" + email, + nickname + phone + number + pet + disclaimer true);' ? What is the &email=, is that my email? – justinae Feb 19 '14 at 17:00
  • I think I see. It's xmlhttp.open("GET","form.php?name=" + name + "&email=" + email, + "&nickname" + nickname + "&phone" + phone + "&number" + number + "&pet" + pet + "&disclaimer" + disclaimer true); – justinae Feb 19 '14 at 17:04
  • Correct! That is called a Query string, PHP will receive those vars as: `$_GET['name']` `$_GET['email']` etc ... – António Almeida Feb 19 '14 at 17:06
  • Hmm. On the live site (http://first_books.justineuteneier.com/contact.php) all the erros work and when I click send it doesn't do anything. I added. form.php to the action in the html but that didn't change anything. – justinae Feb 19 '14 at 17:17
  • You get a +1 now that link is gone ;) Don't forget to link people to w3fools.com if you see them referencing w3schools, spread the word! :) – Bill Feb 19 '14 at 17:19
  • `xmlhttp.open("GET","your_url.php?name` do you change it here? from `your_url.php` to `form.php` ? – António Almeida Feb 19 '14 at 17:20
  • Also, change this: `$_POST['name'];` to `$_GET['name'];` because you are using `GET` ... – António Almeida Feb 19 '14 at 17:20
  • Yes I changed to form.php?name. Do I need to change the name to the name of my form? I changed the $_POST to $_GET and also my form method was post so changed that the get. It's still not working. Is it best to share with the live link or JSfiddle? Updated JSfiddle: http://jsfiddle.net/justinae/Ehg36/ – justinae Feb 19 '14 at 17:31
  • @justinae I think your code is correct, but you can share your live link with me and I will help you to make a good debug and check where is the problem ... – António Almeida Feb 20 '14 at 08:45
  • @ToniAlmeida http://first_books.justineuteneier.com/contact2.php Thanks! Is there a way to send you a PM? – justinae Feb 20 '14 at 15:30
  • @justinae, I created a chat room: http://chat.stackoverflow.com/rooms/47971/justinae-debate we can talk there ... – António Almeida Feb 20 '14 at 15:59
  • This answer unfortunately contains several errors and shortcomings. One being: `var name = document.getElementById('name').innerHTML; var email = document.getElementById('name').innerHTML;` (both use the element with id name). Another being that the radio boxes are not even considered. – nex Nov 15 '15 at 14:03
  • @nex, that was a copy past typo, its fixed. – António Almeida Nov 20 '15 at 15:56
4

In modern browsers, you can use fetch in just a few lines:

fetch(form.action, {
  method: form.method,
  body: new URLSearchParams(new FormData(form)),
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

I also published a slightly more complex version of this as an npm package, if you don't like copy-pasting code from StackOverflow: push-form

fregante
  • 29,050
  • 14
  • 119
  • 159
1
formElem.onsubmit = async (e)  =>
{
    var url = document.getElementById("formElem").getAttribute("action");
    e.preventDefault();
    var data =  new FormData(formElem);
    data.append("submit", "Submit");
    let response = await fetch(url, 
    {
        method: 'POST',
          body: data
    });
    let result = await response.json();
    document.getElementById("field").value = "";
    document.getElementById('charNum').innerHTML="0";
    setTimeout(function autoscroll(){
    var div = document.getElementById('loadmsg');
    div.scrollTop = div.scrollHeight - div.clientHeight; 
    },1000);
  
  };
Wprog_dy
  • 67
  • 5