0

I've copied the Client-Side form validation from MDN and editied it a little bit.

When I type anything into the input field I get this errors...

Uncaught TypeError: Cannot set property 'textContent' of null at showError (validation.js:74) at HTMLInputElement.lnl (validation.js:37)

Uncaught TypeError: Cannot set property 'textContent' of null at showError (validation.js:104) at HTMLInputElement.fnl (validation.js:23)

Uncaught TypeError: Cannot set property 'textContent' of null at showError (validation.js:108) at HTMLInputElement.eml (validation.js:48)

Uncaught TypeError: Cannot set property 'textContent' of null at showError (validation.js:108) at HTMLInputElement.check (validation.js:63)

I'm sure there is a simple solution, but I can't seem to figure it out (I've read through a bunch of questions here on SO, but I can't seem to find a solution.).

function check (event) {
  // if the email field is valid, we let the form submit

 if(!fname.validity.valid || !lname.validity.valid || !email.validity.valid) {
    // If it isn't, we display an appropriate error message
  showError();
    // Then we prevent the form from being sent by canceling the event
  event.preventDefault();
 }
};
document.getElementById('submit_ok').addEventListener('click', check);

function showError() {
 if(fname.validity.valueMissing) {
    // If the field is empty
    // display the following error message.
  fnameError.textContent = 'You need to enter your name.';
 } else if(fname.validity.typeMismatch) {
    // If the field doesn't contain an email address
    // display the following error message.
  fnameError.textContent = 'Name should contain only letters.';
 } else if(fname.validity.tooShort) {
    // If the data is too short
    // display the following error message.
  fnameError.textContent = 'Name must contain at least 2 characters';
 } else if (fname.validity.tooLong) {
  fnameError.textContent = 'Name should contain no more then 45 characters.';
 }
<form accept-charset="UTF-8" name="form" onsubmit="return false;" method="post" id="form">
 <input type="text" oninvalid="This field may contain only letters from A to z." pattern="[A-Za-z][^0-9]{1,25}" 
 name="fname" id="fname" required maxlength="50" minlength="1" placeholder="Janez"/><br />
 <span class="error fn" aria-live="polite"></span>
 <input type="text" oninvalid="This field may contain only letters from A to z." pattern="[A-Za-z][^0-9]{1,25}" 
 name="lname" id="lname" required maxlength="50" minlength="1" placeholder="Novak"/><br />
 <span class="error ln" aria-live="polite"></span>
 
 <span class="lng sl radioS">Spol: </span>
 <span class="lng en radioS">Gender: </span>
 <span class="lng de radioS">Spol DE: </span>
 <span class="lng it radioS">Gendero IT: </span>
 <span class="lng hr radioS">Spolov HR: </span>
 <span class="lng ru radioS">Spol RU: </span><br /><br />
  <div class="radioC"><label><input type="radio" name="spol" id="spM" value="M"> <span class="lng sl">Moški SI</span>
                    <span class="lng en">Moški EN</span>
                    <span class="lng de">Moški DE</span>
                    <span class="lng it">Moški IT</span>
                    <span class="lng hr">Moški HR</span>
                    <span class="lng ru">Moški RU</span>
  </label></div><br />
  <div class="radioC"><label><input type="radio" name="spol" id="spZ" value="Z"> <span class="lng sl">Ženski SI</span>
                    <span class="lng en">Ženski EN</span>
                    <span class="lng de">Ženski DE</span>
                    <span class="lng it">Ženski IT</span>
                    <span class="lng hr">Ženski HR</span>
                    <span class="lng ru">Ženski RU</span>
  </label></div><br />
  <div class="radioC"><label><input type="radio" name="spol" id="spO" value="O"> <span class="lng sl">Ostalo SI</span>
                    <span class="lng en">Ostalo EN</span>
                    <span class="lng de">Ostalo DE</span>
                    <span class="lng it">Ostalo IT</span>
                    <span class="lng hr">Ostalo HR</span>
                    <span class="lng ru">Ostalo RU</span>
  </label></div><br /><br />
  
 <input type="email" name="email" id="email" autofocus="autofocus" autocorrect="off" 
 autocapitalize="off" maxlength="45" required placeholder="moj@email.si"/>
 <br />
 <span class="error em" aria-live="polite"></span>
 <input type="button" value="Submit" id="submit_ok" name="submit_ok" /> <br />

The live preview can be found here, the JS file with the errors is called validate.js.

Thank you for the help

Lelio Faieta
  • 5,913
  • 6
  • 34
  • 57
DrDoom
  • 287
  • 1
  • 9

1 Answers1

1

The problem here is that fnameError is null. querySelector('#fname + span.error.fn') does not return your span, because you have a br element between the input and the span.

I suggest you to give the span errors its own ID. For example, fnameError, and retrieve them with querySelector('#fnameError').

Or, you could change your selectors:

const fnameError = document.querySelector('#fname + br + span.error.fn');

I forked your plunk with this last solution: https://plnkr.co/edit/rgmxmu53drcO2zLQ533k

Additionally, I'd recomend you to make your code less specific, so you don't need to define global constants for your form fields. I'd also show the users all errors in the form when they click 'submit', instead of showing them one by one (which you are doing as your showErrors function is a large if-else-if statement)

Oscar Paz
  • 16,845
  • 3
  • 21
  • 36
  • Thank you. How could I write this less specificly? I am not inputing and arguments into the function... – DrDoom Jan 29 '20 at 11:49
  • 1
    Well, you'd need a validate function that would iterate over all the fields in your form, and check for errors. You could indicate which validations to perform in each field by adding attributes to them. Then, based on those attributes, you use different validations functions on the content of the field. Then you just show the errors for each field. – Oscar Paz Jan 29 '20 at 12:00
  • one more question. When I try and input a number into the name / surname field, I get no error message. the error field just gets padded a little bit... it seems like `typeMissmatch` doesn't work on `input type="text"`. Any idea how I could solve this? – DrDoom Jan 29 '20 at 12:21
  • The input turns red, which means the input is invalid. It isn't showing and error, because the error is not typeMismatch. A 'text' field can have any string. typeMismatch works only for inputs of type 'url' and 'email'. The error you get here is caused by the `pattern` attribute, so you must look for 'patternMismatch' in your `showErrors` function. Check it now: https://plnkr.co/edit/Wf2vYCOOhEqJdL7uq8XV?p=preview – Oscar Paz Jan 29 '20 at 12:33
  • I though type="text" was limited to letters and type="number" was for numbers. Thank you! – DrDoom Jan 29 '20 at 12:37
  • No. `type="text"` if for basically anything. I mean, numbers are valid text, emails are valid text, urls are valid text... – Oscar Paz Jan 29 '20 at 12:42
  • Yea. Thanks =) I looked up typeMismatch MDN and I saw it was valid for urls and emails. I didn't know where I got the red padded field from. Thanks for pointing out the pattern mismatch. – DrDoom Jan 29 '20 at 12:57
  • So, I've edited my code a bit more and I removed this part of the pattern `{1,25}` and `maxlength="50" minlength="1"` from the HTML. Now, when I insert more then 2 characters into the input field I get the pattern mismatch message. Why would that be? If I leave '{1,25}' inside the pattern I can input 27 characters before getting the pettern mismatch error... https://plnkr.co/edit/Gha31S3kGbOCH7hBvvwu?p=preview – DrDoom Jan 29 '20 at 13:12
  • Well, if you remove {1,25}, it means that you match exactly one occurrence. So, your regular expression says: _one letter and another character that is not a number_, while the previous expression said _one letter and between 1 and 25 characters that are not numbers_. – Oscar Paz Jan 29 '20 at 14:18
  • If I leave `pattern="[A-Za-z][^0-9]"` inside the input field, doesn't this mean that they can input anything from Aa to Zz (no numbers), **unlimited** characters as I did not set min/max length? – DrDoom Jan 29 '20 at 14:31
  • 1
    No. `[a-z]` means, literally, 'a character between a and z'. `[a-z]*` means 'a series of characters, between a and z, including no characters'. `[a-z]+` means 'at least one character between a and z, up to unlimited'. I recommend you to read more about regular expressions if you have so many doubts about them. – Oscar Paz Jan 29 '20 at 14:43
  • I did read through it at one point but I've already forgotten most of it as I don't use it that often. Will need to re-read it I guess. Thank you. – DrDoom Jan 29 '20 at 14:46
  • Yes, developers usually understimate the power of regular expressions. They help problems in a way that would take lots of lines of code otherwise – Oscar Paz Jan 29 '20 at 14:47