2
\$\begingroup\$

Created a validation form in vanilla JS. Due to my little experience, I have a bunch of "if" here, I can not transfer the coordinates of Yandex.Maps to another function for validation, and it is still unknown what. With the coordinates, I "crutch" by saving them to an invisible div :-) I deleted my Api key, so I won't be able to get the coordinates in the example, I don't know if it's worth giving the key to public access :-) The code is working.

Tell me how I can reduce the code or how to perform form validation without my crutch using a div :-) (pass the variable to another function so that when the button is clicked, it checks that the coordinates are entered)

let errorName = document.querySelector(".name-error");
let errorNumber = document.querySelector(".number-error");
let errorEmail = document.querySelector(".email-error");
let errorMap = document.querySelector(".map-error");
let completed = document.querySelector(".mailForm__completed");
function viodChecker() {
 let name = document.querySelector(".mailForm__name").value;
 let number = document.querySelector(".mailForm__number").value;
 let Email = document.querySelector(".mailForm__email").value;
 let Coords = document.querySelector(".coords");
 if (name === "") {
 errorName.style.display = "block";
 }
 if (name !== "") {
 errorName.style.display = "none";
 }
 if (number === "") {
 errorNumber.style.display = "block";
 }
 if (number !== "") {
 errorNumber.style.display = "none";
 }
 if (Email.indexOf("@") === -1) {
 errorEmail.style.display = "block";
 }
 if (Email.indexOf("@") !== -1) {
 errorEmail.style.display = "none";
 }
 if (Email.indexOf("@") !== -1) {
 errorEmail.style.display = "none";
 }
 if (Coords.textContent === "") {
 errorMap.style.display = "block";
 }
 if (Coords.textContent !== "") {
 errorMap.style.display = "none";
 }
 if (name !== "" && number !== "" && Email.indexOf("@") !== -1 && Coords.textContent !== "") {
 completed.style.display = "block";
 }
}
ymaps.ready(init);
function init() {
 var myPlacemark,
 myMap = new ymaps.Map('map', {
 center: [40.391917, -73.524590],
 zoom: 17,
 controls: ['geolocationControl', 'searchControl']
 });
 // We listen to the click on the map.
 myMap.events.add('click', function (e) {
 var coords = e.get('coords');
 // If the label has already been created, just move it.
 if (myPlacemark) {
 myPlacemark.geometry.setCoordinates(coords);
 }
 // If not, we create.
 else {
 myPlacemark = createPlacemark(coords);
 myMap.geoObjects.add(myPlacemark);
 // Listen to the drag-and-drop event on the label.
 myPlacemark.events.add('dragend', function () {
 getAddress(myPlacemark.geometry.getCoordinates());
 });
 }
 getAddress(coords);
 });
 // Create a label.
 function createPlacemark(coords) {
 return new ymaps.Placemark(coords, {
 iconCaption: 'search...'
 }, {
 preset: 'islands#violetDotIconWithCaption',
 draggable: true
 });
 }
 // Coords
 function getAddress(coords) {
 myPlacemark.properties.set('iconCaption', 'поиск...');
 ymaps.geocode(coords).then(function (res) {
 var firstGeoObject = res.geoObjects.get(0);
 myPlacemark.properties
 .set({
 // We form a line with data about the object.
 iconCaption: [
 firstGeoObject.geometry.getCoordinates(),
 ].filter(Boolean).join(', '),
 // We set the line with the object address as the balloon content.
 balloonContent: firstGeoObject
 });
 document.querySelector(".coords").textContent = firstGeoObject.geometry.getCoordinates();
 });
 }
}
body, .mailForm {
 display: flex;
 align-items: center;
 justify-content: center;
 flex-direction: column;
}
input, textarea {
 font-size: 14px;
 margin: 10px 0 0 0;
 width: 350px;
 resize: none;
}
.mailForm__map {
 margin-top: 10px;
}
button {
 margin: 10px 0 0 0;
 font-size: 14px;
 cursor: pointer;
}
.mailForm__comment {
 display: inline-block;
 height: 200px;
}
.mailForm__error, .mailForm__completed, .coords {
 display: none;
 color: red;
 font-size: 16px;
 font-weight: bold;
 margin-top: 10px;
}
.mailForm__completed {
 color: green;
 font-size: 20px;
}
<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <link href="style.css" rel="stylesheet">
 <title>Mail Form</title>
 <script src="https://api-maps.yandex.ru/2.1/?apikey=5200498b-0123-4796-1-bee4ea5473212&lang=ru_RU" type="text/javascript">
 </script>
</head>
<body>
 <div class="mailForm">
 <input class="mailForm__name" placeholder="Name" type="text" value="">
 <input class="mailForm__number" placeholder="Tel" type="tel" value="">
 <input class="mailForm__email" placeholder="Email" type="email" value="">
 <div id="map" class="mailForm__map" style="width: 100%; height: 200px">
 </div>
 <textarea class="mailForm__comment" maxlength="500" placeholder="Comment" type="text" value=""></textarea>
 <button onclick="viodChecker()">SEND</button>
 <div class="mailForm__error name-error">NAME ERROR</div>
 <div class="mailForm__error number-error">TEL ERROR</div>
 <div class="mailForm__error email-error">@ ERROR</div>
 <div class="mailForm__error map-error">COORDS ERROR</div>
 <div class="mailForm__completed">NICE!</div>
 <div class="coords"></div>
 </div>
 <script src="script.js"></script>
</body>
</html>

asked Dec 11, 2020 at 5:52
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

DRYing the ifs One option would be to use else, or even better, the conditional (ternary) operator instead of having two separate blocks for each validator:

errorName.style.display = name ? 'none' : 'block';
errorNumber.style.display = number ? 'none' : 'block';
errorEmail.style.display = email.includes('@') ? 'none' : 'block';
errorMap.style.display = Coords.textContent ? 'block' : 'none';

(You could also use a CSS class for this instead, and use classList.toggle and a second argument)

But for the inputs, rather than having these manual error divs, consider using the HTML to force validation instead. Put the inputs into a <form>, and then:

  • For the name and number, use the required attribute - the user's browser will tell them to fill out the fields
  • For the email, use the type="email" attribute, and the user's browser will validate the email address (more reliably than just checking for @s).

Div crutch Rather than using a <div> to populate the getCoordinates results, you can save in an outer variable, eg:

// top level
let coords;
// ...lots of code
 coords = firstGeoObject.geometry.getCoordinates();

Then rather than checking Coords.textContent, check the contents of the variable coords.

Other suggestions:

Always use const when you can - only use let when you must warn readers of the code that you may be reassigning the variable later in the code. 95% of variable declarations can be with const, usually.

On a similar note:

If you're writing in modern syntax (which you are, and you should!), never use var - var has the same problems as let, but also has issues with having unintuitive function scope instead of block scope, and of being automatically assigned to a property of the global object when on the top level.

Catch asynchronous errors, don't ignore them - currently, if .geocode throws, no indication will be given to the user, and they may well be confused. When dealing with a Promise, usually you'll want to follow a pattern like:

someProm
 .then((result) => {
 // do stuff with result
 })
 .catch((err) => {
 // there was an error, inform the user and maybe log it for debugging
 });

Avoid inline event handlers, they have too many problems to be worth using nowadays, including a demented scope chain and requiring global pollution. Instead, add the event listener using JavaScript instead, eg:

document.querySelector('.mailform > button').addEventListener('click', viodChecker);
Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
answered Dec 11, 2020 at 6:12
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.