Manipulating elements on the webpage and customizing the appearance for validating forms in the

To automatically display an error message next to the input field when submitting a form without any data or with incorrect email parameters, I am using local DOM manipulation with HTML, CSS, and JS. Unfortunately, I keep encountering an error: Uncaught TypeError: Cannot read properties of undefined (reading 'remove') at HTMLButtonElement.

"use strict"

const form = document.querySelector(".form");
const inputs = document.getElementsByTagName("input");
const errorImg = document.querySelectorAll(".error-img");
const submitBtn = document.getElementById("submit-btn");


submitBtn.addEventListener("click", (e) => {
    e.preventDefault();

    if(!inputs.value){
        errorImg.classList.remove("hidden");
    } else {
        errorImg.classList.add("hidden");
    }
});
@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap);

body{
    margin: 0;
    background-image: url(images/bg-intro-desktop.png);
    background-color: rgba(255, 0, 0, .5);
    font-family: 'Poppins', sans-serif;
}

.container{
    margin: 6rem auto;
    height: auto;
    width: 70%;
    
    display: grid;
    grid-template-areas: 
    "left right"
    "left right";
    grid-auto-columns: minmax(0, 32rem);
}

.left-container{
    grid-area: left;
}

.left-heading{
    color: white;
    font-size: 2.7rem;
    line-height: 3rem;
    font-weight: 700;

    position: relative;
    top: 30%;
}

.left-content{
    color: white;
    font-size: .9rem;
    font-weight: 400;

    position: relative;
    top: 29%;
}

.right-container{
    grid-area: right;
}

.right-top-container{
    background-color: hsl(248, 32%, 49%);
    border-radius: .5rem;
    height: 11.5%;
    margin: auto auto 1.5rem auto;
    box-shadow: 0px 6px 1px rgba(0, 0, 0, .2);
}

.top-text-special{
    color: white;
    font-weight: 600;
    font-size: .85rem;

    position: relative;
    top: 50%;
    left: 72%;
    transform: translate(-50%, -50%);
}

.top-text{
    color: white;
    font-weight: 400;
}

.right-form{
    background-color: white;
    height: 23rem;
    border-radius: .5rem;
    padding: 1.5rem;
    padding-top: 2.5rem;
    box-shadow: 0 7px 1px rgba(0, 0, 0, .15);

    display: grid;
    grid-template-areas: 
    "fname"
    "lname"
    "email"
    "password"
    "submit-btn"
    "bottom-text";
}

input{
    font-family: 'Poppins', sans-serif;
    font-weight: 500;
    font-size: .8rem;

    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    padding: 0 0 0 1.5rem;

    height: 130%;
    width: 90%;

    border: solid;
    border-width: .09rem;
    border-radius: .4rem;
    border-color: hsl(246, 25%, 77%);
}

.first-name-div{
    grid-area: fname;
    margin: 0 0 7% 0;

    position: relative;
}

.last-name-div{
    grid-area: lname;
    margin: 0 0 7% 0;

    position: relative;
}

.email-div{
    grid-area: email;
    margin: 0 0 7% 0;

    position: relative;
}

.password-div{
    grid-area: password;
    margin: 0 0 7% 0;

    position: relative;
}

.submit-btn-div{
    grid-area: submit-btn;
}

#submit-btn{
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 97.1%;
    height: 130%;
    border-radius: .4rem;

    background-color: hsl(154, 59%, 51%);
    border: none;
    color: white;
    box-shadow: 0 2px .5px rgba(0, 0, 0, .4);

    cursor: pointer;
}

.right-footer-text{
    grid-area: bottom-text;
}

.footer-text{
    position: relative;
    top: 50%;
    left: 58%;
    transform: translate(-50%, -50%);

    color: grey;
    font-size: .7rem;
    font-weight: 600;
}

.footer-span{
    color: hsl(0, 100%, 74%);
}

#error-img{
    position: absolute;
    top: 6px;
    right: 22px;
}

.hidden{
    display: none;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FrontEndMentor#3</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="shortcut icon" href="images/favicon-32x32.png" type="image/x-icon">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">

</head>
<body>
    <div class="container">
        <div class="left-container">
            <h1 class="left-heading">Learn to code by <br>
                 watching others</h1>
            <p class="left-content">See how experienced developers solve problems in real-time. <br>
                Watching scripted tutorials is great, but understanding how <br>
                developers think is invaluable.</p>
        </div>

        <div class="right-container">
            <div class="right-top-container">
                <p class="top-text-special">Try it free 7 days <span class="top-text">then $20/mo. thereafter</span></p>
            </div>
            <form action="#" class="form">
            <div class="right-form">
                <div class="first-name-div">
                    <input type="text" name="fname" id="first-input" placeholder="First Name">
                    <img class="error-img hidden" src="images/icon-error.svg" alt="">
                </div>
                <div class="last-name-div">
                    <input type="text" name="lname" id="last-input" placeholder="Last Name">
                    <img class="error-img hidden" src="images/icon-error.svg" alt="">
                </div>
                <div class="email-div">
                    <input type="email" name="email-address" id="email" placeholder="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8beef3eae6fbe7eecbeee6eae2e7a5e8e4e6">[email protected]</a>">
                    <img class="error-img hidden" src="images/icon-error.svg" alt="">
                </div>
                <div class="password-div">
                    <input type="password" name="password" id="password" placeholder="Password">
                    <img class="error-img hidden" src="images/icon-error.svg" alt="">
                </div>
                <div class="submit-btn-div">
                    <button type="submit" id="submit-btn">CLAIM YOUR FREE TRIAL</button>
                </div>
            </form>
                <div class="right-footer-text">
                    <p class="footer-text">By clicking the button, you are agreeing to our <span class="footer-span">Terms and Services</span></p>
                </div>
            </div>
        </div>
    </div>
    <script src="index.js"></script>
</body>
</html>

Answer №1

querySelectorAll returns a collection of elements. Since a collection is not an HTML node, it does not have the attribute classList. The object errorImage[0] contains the classList attribute.

Trying to call errorImage.classList.remove on a collection will result in an undefined property error because collections do not have classList defined. Accessing properties of undefined objects leads to errors as undefined is a primitive data type.

You can use

const errImgs = document.querySelectorAll(".error-img");

errImgs.forEach(errImg =>
 errImg.classList.remove("hidden")
);

This code snippet removes the specific class from all images in the collection

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The ng-switch function is not generating the desired code output

In my Ionic app, I have the following code snippet that I am currently viewing with ionic serve. However, when the initial ng-switch statement triggers... <span ng-switch="post.enclosure"> <span ng-switch-when="[]"> <p>def&l ...

Access and listen to the stored blob file that contains MP3 audio

Essentially, I am looking to stream a blob MP3 file in Firefox. I have both the blob itself: blob (sliced with mime type audio/mpeg3), and its URL: blobURL = window.URL.createObjectURL(blob). I attempted to do so using: an HTML5 audio player: <audi ...

Identifying the completion of scrolling within a container

I'm facing a challenge with my dynamic website that has numerous blog posts. My goal is to initially load only four posts and then add another four as the user scrolls to the end of the page. While I have figured out how to handle this on the backend, ...

Issue encountered while trying to utilize the reset function of the FormGroup with the angular2-tinymce plugin

I utilized the FormGroup feature to construct my form, and I required a textarea component. I decided to use the angular2-tinymce library/package to create the form. Here is my HTML template: <form (submit)="submitCallLog($event)" [formGroup]="callLo ...

The Selenium Action class is failing to perform a second mouse hover on the same web element

Actions action = new Actions(Driver); action.MoveToElement(webelement).ClickAndHold().Perform(); The code snippet above is used to perform a mouse hover on a Web Element, and it works perfectly the first time. However, when attempting to do the mouse hove ...

What steps should I take to make my Vue JS delete function operational?

As I work on developing my website, I've encountered some challenges. Being new to coding, I'm struggling with creating a functional delete user button. When I click delete, it redirects me to the delete URL but doesn't remove the entry from ...

The Controller received a JSON object that was empty

I know this question has been asked countless times, but I've tried all solutions with no success. Here's the JSON object in question: { "manufacture":"HP", "model":"testModel", "serialNumber":"testSerial", "description":"Test Descript ...

angularjs potentially unsafe:data warning appears when taking a screenshot using html2canvas

While using angularjs and html2canvas for capturing a screenshot, I have encountered some issues. The screenshot captures successfully on some screens, but not on others. I am getting the following error: https://i.sstatic.net/FVNym.png I have tried to re ...

Troubleshooting a JSON error encountered while utilizing the mongoimport tool

Currently, I am utilizing the mongoimport utility to import data from a json file into mongodb with the following command: mongoimport --db city --collection inspections ./city_inspections.json #mongo import utility The json data structure looks like this ...

Is it possible to nest v-for directives within a component file?

Even after going through the VueJS tutorials multiple times, I am still unable to find a solution to this problem. My issue revolves around displaying a list of lists using accordions, which is supposed to work smoothly with vue-strap components. For exa ...

Tips for avoiding problems with quoting and using apostrophes in a JavaScript function inside a tag in a JSP file

Within my JSP, I have a string value stored in ${state.status.code} that I need to pass to a JavaScript function when a table element is clicked using onClick to trigger the showStatus function. Here is how I have attempted to achieve this: <c:set var= ...

Setting CSS margins to properly align a list next to a float-left image

Here's my initial attempt at coding a reddit-style comment using html and css. I have some inquiries about the css and overall structure: How can I align the comment body ("The King took off his hat...") with the comment head ("Nathan, posted...") a ...

Animating the maximum height causes a delay in the performance of other elements

Attempting to adjust the maximum height of a ul. When the max-height property changes (via toggling a class), the height shifts immediately, while the items below the ul maintain the animated height as expected. var expander = $('.skill-expand&apos ...

Angular 2 decorators grant access to private class members

Take a look at this piece of code: export class Character { constructor(private id: number, private name: string) {} } @Component({ selector: 'my-app', template: '<h1>{{title}}</h1><h2>{{character.name}} detai ...

"Implementing a function triggered by a change event within a concealed input

I am working with two AJAX functions. The first function takes the input from the first field, concatenates a string to it, and then updates the value of the second hidden input field. However, the second function is supposed to detect any changes in thi ...

Regular expression that allows alphanumeric characters and spaces, but does not permit spaces at the beginning or end of the

I need to create a regular expression that allows for a combination of letters, numbers, and spaces within a word, ranging in length from 3 to 50 characters, but without spaces at the beginning or end of the string. Here is the regex pattern I have come up ...

In the process of creating my initial discord bot, struggling to incorporate advanced functionalities beyond basic commands

I am currently using discord.js and JavaScript to code. I have created a test bot and followed step-by-step guides meticulously, but the bot only responds to basic "ping pong" commands. Whenever I try to add more complex commands, the bot stops functioning ...

What is the best way to display an additional component upon logging out in a React application that utilizes

Is there a way to render a different component when logging out of firebase? I am attempting to refresh the page to display the LoginPage. Here is my LoginPage that is shown when logging in with a different form. import React, { Component } from "react" ...

Stop Antd Modal from automatically scrolling to the top

At the moment, I'm utilizing Ant Design (v4.22.8) and Next.js (v12.3.4) in my project. One issue I've encountered is with a Modal component that activates when a button is clicked. Instead of overlaying the current content on the screen, the moda ...

Tasks should be defined prior to being referenced in order to avoid any issues

Utilizing multiple files with gulp@4, the main gulpfile.js includes all other files within the ./tasks/ directory. We have implemented the npm gulp-hub package to incorporate multiple gulpfiles within the ./tasks/ directory. However, upon calling the tasks ...