I have an html form used as a subscription form. The form is sent via POST method to PHP file for processing and database entry. Form validation is done via JavaScript.
I don't want to redirect to the PHP file and I want to keep my form styling. That is, when the user clicks on the SUBMIT button the form animates and displays a Success message on-page without reloading or sending to the php file.
I have tested the PHP file alone and it works fine, writing as expected in mySQL database table. The JavaScript validation file also works great on its own. The problem is that when the Submit button is clicked, after all required fields are valid, the form animates as if data is sent successfully, but no data gets written into my database. I tried inserting AJAX in different formats at different place in the JavaScript code but nothing worked.
The JS Validation file is linked to via in the HTML file. And the PHP file is linked to via the Form Action="" attribute.
When I use the following script in the HTML alongside the link to form.js :
<script type="text/javascript">
$("#submitBtn").click(function() {
var dataString = $('#register').serialize();
$.ajax({
type: "POST",
url: "contact/validate.php",
data: dataString
});
});
</script>
It actually works - the form animates as intended, there is no redirect to the PHP file and form data gets written into the database, but this makes dublicate entries and also allows non-valid entries to be written into the database, despite the JavaScript-initiated error messages on the input fields.
Here is my HTML Form:
<div id="contactForm" class="contactForm">
<div id="formHeader" class="formHeader">
<h2 id="message">Форма за регистрация</h2>
</div>
<div id="formBody" class="formBody">
<form action="contact/validate.php" method="POST" name="contactForm" id="register">
<div class="row">
<div class="inputContainer hlf">
<input name="fullname" id="fullname" type="text" placeholder="Вашето име" minlength="2" maxlength="40" required tabindex="1">
</div>
<div class="inputContainer hlf">
<input name="location" id="location" type="text" placeholder="Населено място" minlength="5" maxlength="40" required tabindex="2">
</div>
</div>
<div class="row">
<div class="inputContainer hlf">
<input name="email" id="email" type="email" placeholder="Ваш имейл за контакт" maxlength="75" required tabindex="3">
</div>
<div class="inputContainer hlf">
<input name="phone" id="phone" type="tel" placeholder="Телефон" pattern="[0-9 ]" maxlength="15" tabindex="4">
</div>
</div>
<div class="row">
<div class="inputContainer">
<textarea name="comment" id="comment" rows="4" placeholder="Допълнителен коментар" minlength="5" maxlength="250" tabindex="5"></textarea>
</div></div>
<input id="submitBtn" class="submitBtn" type="submit" value="Изпрати">
</form>
</div>
Here is my PHP File:
<?php
//Clean form data from backslashes and evil tags
//define variables and set to empty values
$fullname = $location = $email = $phone = $comment = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$fullname = test_input($_POST["fullname"]);
$location = test_input($_POST["location"]);
$email = test_input($_POST["email"]);
$phone = test_input($_POST["phone"]);
$comment = test_input($_POST["comment"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
//All input is tested and validated, now connect to DB and send data to the mySQL database table:
$servername = "localhost";
$username = "usename";
$password = "password";
$dbname = "database name";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO subscribed (fullname, location, email, phone, comment)
VALUES ('$fullname', '$location', '$email', '$phone', '$comment')";
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
Finally, here is my JavaScript validation file:
$(function() {
"use strict";
var //GLOBAL VARIABLES
input,
container,
//CSS CLASSES
classSuccess = "success",
classError = "error",
//FORM VALIDATOR
formValidator = {
init: function() {
this.cacheDom();
this.bindEvents();
},
cacheDom: function() {
//MAIN PARENT ELEMENT
this.contactForm = document.getElementById("contactForm");
//MAIN FORM ELEMENTS
this.formHeader = document.querySelector("#formHeader h2");
this.formBody = document.getElementById("formBody");
this.inputContainer = document.getElementsByClassName("inputContainer");
//USER INPUT ELEMENTS
//INPUT FIELDS
this.fields = {
fullname: document.getElementById("fullname"),
location: document.getElementById("location"),
email: document.getElementById("email")
};
this.submitBtn = document.getElementById("submitBtn");
},
bindEvents: function() {
var i;
//RUN RULES ON SUBMIT BUTTON CLICK
this.submitBtn.onclick = this.runRules.bind(this);
//BIND EVENTS TO EACH INPUT FIELD
for (i in this.fields) {
if (this.fields.hasOwnProperty(i)) {
//VARIABLES
input = this.fields[i];
container = input.parentElement;
//RUN RULES WHEN INPUT HAS FOCUS
input.onfocus = this.runRules.bind(this);
//RESET ERRORS WHEN CONTAINER IS CLICKED
container.onclick = this.resetErrors.bind(this, input);
}
}
},
runRules: function(evnt) {
var target = evnt.target,
type = evnt.type;
//IF EVENT ON SUBMIT BUTTON
if (target === this.submitBtn) {
//PREVENT FORM SUBMITTION
this.preventDefault(evnt);
//IF INPUT HAS FOCUS
} else if (type === "focus") {
//RESET CLASSLIST
this.resetClassList(target.parentElement);
//RESET ERRORS
this.resetErrors(target);
return false;
}
//RESET CLASSLIST
this.resetClassList();
//CHECK FIELDS
this.checkFields();
},
preventDefault: function(evnt) {
//PREVENT DEFUALT
evnt.preventDefault();
},
checkFields: function() {
var i,
validCount = 0,
//EMAIL FILTER
filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
//CYLCE THROUGH INPUTS
for (i in this.fields) {
if (this.fields.hasOwnProperty(i)) {
input = this.fields[i];
//CHECK IF FIELD IS EMPTY
if (input.value === "") {
//ADD ERROR CLASS
this.addClass(input, classError);
//CHECK IF EMAIL IS VALID
} else if (i === "email" && !filter.test(input.value)) {
//ADD ERROR CLASS
this.addClass(input, classError);
} else {
//FIELD IS VALID
this.addClass(input, classSuccess);
validCount += 1;
}
}
}
//IF ALL FIELDS ARE VALID
if (validCount === 3) {
//SUBMIT FORM
this.submitForm();
}
},
addClass: function(input, clss) {
container = input.parentElement;
//IF INPUT HAS ERROR
if (clss === classError) {
//SHOW ERROR MESSAGE
this.errorMessage(input);
}
//ADD CLASS
input.parentElement.classList.add(clss);
},
errorMessage: function(input) {
var message;
//IF NAME HAS ERROR
if (input === this.fields.fullname) {
message = "Моля, въведете пълно име";
//ELSE IF LOCATION HAS ERROR
} else if (input === this.fields.location) {
message = "Моля, въведете град/село";
//ELSE IF USEREMAIL HAS ERROR
} else if (input === this.fields.email) {
message = "Има грешка в имейла";
}
this.renderError(input, message);
},
renderError: function(input, message) {
var html;
//GET INPUT CONTAINER
container = input.parentElement;
//RENDER HTML
html = document.createElement("div");
html.setAttribute("class", "message");
html.innerHTML = message;
//IF MESSAGE ELEMENT DOESN'T EXIST
if (!container.getElementsByClassName("message")[0]) {
//INSERT MESSAGE TO INPUT CONTAINER
container.insertBefore(html, container.firstElementChild);
}
},
resetClassList: function(input) {
var i;
//IF TARGETING SPECIFIC INPUT
if (input) {
//GET INPUT CONTAINER
container = input.parentElement;
//REMOVE CLASSES
container.classList.remove(classError, classSuccess);
//FOCUS ON INPUT FIELD
input.focus();
} else {
for (i in this.fields) {
if (this.fields.hasOwnProperty(i)) {
//REMOVE CLASSES FROM ALL FIELDS
this.fields[i].parentElement.classList.remove(classError, classSuccess);
}
}
}
},
resetErrors: function(input) {
//GET INPUT CONTAINER
container = input.parentElement;
//IF CONTAINER CONTAINS ERROR
if (container.classList.contains(classError)) {
//RESET CLASSES
this.resetClassList(input);
}
},
submitForm: function() {
var waitForAnimation;
//ADD SUCCESS CLASS
this.contactForm.classList.add(classSuccess);
//WAIT FOR ANIMATION TO FINISH
this.changeHeader("Регистрацията е успешна!");
//WAIT FOR ANIMATION TO FINISH
setTimeout(this.changeHeader.bind(this, "ДОБРЕ ДОШЛИ!"), 1800);
},
changeHeader: function(text) {
//CHANGE HEADER TEXT
this.formHeader.innerHTML = text;
}
};
//INITIATE FORM VALIDATOR
formValidator.init();
}());