How to validate a form with JavaScript prior to mailto action OR Change a form action using JavaScript

html5

#1

Hello All,

Below is an excerpt of my form code.
I have a two part question:

1) How do I call the validation script in a way that it does not send the invoke the mailto email “post” until AFTER the input is validated?

2) Is there a way to use JavaScript to either :
_ a) send an email._
_ b) Change the action of a form (i.e., change from action: “” TO action: mailto: email@email.com)_

<html>
<head></head>
<body>

<form name="contact" id="contact" action="mailto: email@domain.com" method="post" enctype="text/plain" onsubmit="valEmail()">

<label>Email:</label><input type="text" name="email" id="email">
            
<input type="submit" value="Send">
</form>
</body>
</html>

I also have a validation script for the email address. It was designed to check the email form and the length of the email address as being 6 characters or longer. (I understand the 6 character check isn’t necessary, I just wanted to test out a theory)

<script>

function valEmail() {
	var emailstr = document.getElementById("email").value;
	var emform =/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (emform.test(emailstr)) {
		alert("Email Accepted");
		}
		else {
		alert("Please enter an email address");
	        }
}
</script>

When I could get the code to work, the email was sent BEFORE the user input is validated.

(I understand that there may be a better way of accomplishing my tasks. I also understand that mailto is not the most accurate/secure way of accomplishing this task. However, I am still learning JavaScript, so suggestions are welcome.)


#2

Hi @MWms, you can prevent the default action of the event and programmatically send the form if the validation was OK:

var contactForm = document.getElementById('contact')

function validateEmail () {
  var emailstr = document.getElementById('email').value
  var emform = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/

  return emform.test(emailstr)
}

contactForm.addEventListener('submit', function (event) {
  event.preventDefault()

  if (validateEmail()) {
    contactForm.submit()
  } else {
    // Give some sort of error feedback
    contactForm.classList.add('invalid')
  }
})

(BTW I’d avoid inline JS such as onsubmit="valEmail()" as it has a couple of disadvantages, most notably that it violates separation of concerns – the above code doesn’t require any JS in your markup.)

a) No, a form with a mailto action will just open the users email client populated with the form values. If you want to directly send the email, you’d have to submit the form to your backend first, and send the email from there; for example using mail() in PHP. This is generally preferable anyway IMO as it gives you full control over what is actually getting sent and additional backend validation, plus you don’t have to directly expose your own email address to the web.

b) Yes, if you have a reference to your form as in the above snippet, you can set the form action like so:

var contactForm = document.getElementById('contact')

contactForm.action = 'mailto:email@domain.com'

#3

First of all I would like to thank you for providing such a comprehensive response. I actually had forgotten that the mailto action simply opened the users mail client. However, I am happy to report that I am now able to implement the change of action code. Thanks so much for the example.

One follow up question about the code:

contactForm.classList.add('invalid') .

I am not familiar with error feedback (I will do some research as I progress through the lessons). If this code is called,

1) will this code provide the user with an “error message” or would I need to create an alert to accomplish this task?


#4

Well with error feedback I really just meant to notify the user that the form is not valid – using an alert() is one possibility to do so, although a rather obtrusive one (being modal it makes the rest of the page inaccessible until it gets closed). If this is just an exercise then that’s fine, but you usually wouldn’t use it in production.

Now with

document.getElementById('contact').classList.add('invalid')

or actually

document.getElementById('email').classList.add('invalid')

you’d add a class to the corresponding fields, so that you can style them with CSS like e.g.

.invalid {
  border: 1px solid red;
}

You might also consider using the built-in HTML5 form validation, so that you don’t have to bother with regular expressions and all to check if a given value is a valid email – for example

input:invalid {
  border: 1px solid red;
}
<input type="email" required>

There’s also a JS API for that if you need more control (more info in the above link as well).