I am writing a simple web-app with a register-login-logout functionality as a practice task. The backend logic is in PHP, the client side part is in pure HTML/CSS/Javascript. I was asked to make the register/login form dynamically generated according to current scope (register or login), so I decided to generate the form with Javascript and send the form data (and receive validation error messages) to the server with an AJAX request (in JSON format).
The problem is when the form is generated, the AJAX request automatically fires, without clicking the Login/Register button. Moreover, it seems that the function which sends the AJAX request, cannot get the input values from the input fields, so it only sends the scope.
Every time, when the form is regenerated (because the scope has changed) it resends the AJAX request.
I have already tried calling the function when the Login/Register buttons are clicked, and binding the function to the form only when it is generated, but nothing helped.
Here are the functions that send the AJAX:
function sendAjax(data) {
let xhr = new XMLHttpRequest();
xhr.open("POST", "process.php");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
let resData = JSON.parse(this.responseText);
Object.keys(resData).forEach(function (key) {
let e = resData[key];
if(document.getElementById(key+"span")!==null){
let div = document.getElementById(key+"G");
div.classList.add("has-error");
let span = document.getElementById(key+"span");
span.innerHTML = e;
}
});
}
};
xhr.send(data);
}
function process(scope) {
let inputs = document.getElementsByTagName("input");
console.log(inputs);
let filteredInputs = [];
for(let i = 0; i < inputs.length; i++){
if(inputs[i].type !== "submit"){
filteredInputs.push(inputs[i]);
}
}
console.log(filteredInputs);
let data = {scope: scope};
for(let i = 0; i < inputs.length; i++){
data[filteredInputs[i].name] = filteredInputs[i].value;
}
let dataJSON = JSON.stringify(data);
sendAjax(dataJSON);
return false;
}
This is how the form is generated:
let session = {
scope: "login",
setScope: function (scope) {
this.scope = scope;
document.getElementById("form-wrapper").appendChild(createForm(scope));
}
};
function createForm(scope){
if(document.getElementById("form")!==null){
let form = document.getElementById("form");
document.getElementById("form-wrapper").removeChild(form);
}
let form = document.createElement("form");
form.id = "form";
let buttons = document.createElement("div");
buttons.className = "form-group";
let title = document.createElement("h2");
if(scope === "login"){
title.innerHTML = "Bejelentkezés";
form.appendChild(title);
form.appendChild(createFormGroup("email"));
form.appendChild(createFormGroup("password"));
let login = document.createElement("input");
login.type = "submit";
login.className = "btn btn-primary";
login.value = "Bejelentkezés";
login.id = "btn-submit";
buttons.appendChild(login);
}
if(scope === "register"){
title.innerHTML = "Regisztráció";
form.appendChild(title);
formElementProps.forEach(((value, key) => form.appendChild(createFormGroup(key))));
let register = document.createElement("input");
register.type = "submit";
register.className = "btn btn-primary";
register.value = "Regisztráció";
register.id = "btn-submit";
let reset = document.createElement("input");
reset.type = "reset";
reset.className = "btn btn-deafult";
reset.value = "Törlés";
buttons.appendChild(register);
buttons.appendChild(reset);
}
let link = createLink(scope);
form.appendChild(buttons);
form.appendChild(link);
form.onsubmit = process(scope);
return form;
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById("form-wrapper").appendChild(createForm(session.scope));
});
Backend logic is seemingly fine, because when it fires automatically, it responds with the correct error message.