Home > Back-end >  I cannot solve a Uncaught TypeError: Cannot read properties of undefined (reading 'remove'
I cannot solve a Uncaught TypeError: Cannot read properties of undefined (reading 'remove'

Time:07-28

I need to make a change on the icons passing the class .fa-plus to .fa-minus thats for this menu

<div >
                                <h2  id="subseccOne">
                                    <button  type="button" >
                                        <i   data-bs-toggle="collapse" data-bs-target="#subsecollapseOne" aria-expanded="true" aria-controls="subsecollapseOne"></i> <a  href="">SEGUNDO NIVEL </a>
                                    </button>
                                </h2>
                                <div id="subsecollapseOne"  aria-labelledby="subseccOne" data-bs-parent="#subsecc">
                                    <div >
                                        <div  id="accordionExample">
                                            <div >
                                                <h2  id="headingOne">
                                                    <button  type="button" >
                                                         <i   data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne" ></i> <a  href="">  TERCER NIVEL </a>
                                                    </button>
                                                </h2>
                                                <div id="collapseOne"  aria-labelledby="headingOne" data-bs-parent="#accordionExample">
                                                    <div >
                                                        <strong>This is the first item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
                                                    </div>
                                                </div>
                                            </div>
                                            <div >
                                                <h2  id="headingTwo">
                                                    <button  type="button" >
                                                        <i   data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></i> <a  href="">  TERCER NIVEL </a>
                                                    </button>
                                                </h2>
                                                <div id="collapseTwo"  aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
                                                    <div >
                                                        <strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
                                                    </div>
                                                </div>
                                            </div>
                                            <div >
                                                <h2  id="headingThree">
                                                    <button  type="button" >
                                                        <i   data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree"></i> <a  href="">  TERCER NIVEL </a>
                                                    </button>
                                                </h2>
                                                <div id="collapseThree"  aria-labelledby="headingThree" data-bs-parent="#accordionExample">
                                                    <div >
                                                        <strong>This is the third item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>

my JavaScript function is this

const icon= document.querySelectorAll(".fa-solid");
    const plusIcon = document.querySelectorAll(".fa-plus");
    
    
    for (i =0; i < plusIcon.length; i  ){
        plusIcon[i].addEventListener("click", function (){
           
            icon.classList.remove("fa-plus");
            icon.classList.add("fa-minus")
        });
    }

I dont know why the console print this error, When the click event run on tghe function

menu_funcionalidad.js:29 Uncaught TypeError: Cannot read properties of undefined (reading 'remove') at HTMLElement.

CodePudding user response:

You are getting the error because you already assigned icon to a nodeList, so when trying to change the classes, icon is not an individual element. I would suggest using event.target to manipulate the element that has been clicked.

const icon= document.querySelectorAll(".fa-solid");
const plusIcon = document.querySelectorAll(".fa-plus");
    
    
for (i =0; i < plusIcon.length; i  ){
    plusIcon[i].addEventListener("click", e => {
       e.target.classList.remove("fa-plus");
       e.target.classList.add("fa-minus");
       plusIcon.forEach(item => {
         if (item !== e.target) item.classList.add('//class-name');
       });
    });
}

CodePudding user response:

document.querySelectorAll(".fa-solid") will return a nodeList, meaning that when you attempt to access the classList inside your loop, you're attempting to access the classList of a nodeList, which is not possible.

If you want to add/remove the icons for each item in that node list, you can iterate over that list with .forEach() (See more here).

If you want to add/remove the icon from the element you're currently iterating over, replace icon.classList... with i.classList.

If the second route is what you're looking for, you could also add in a check inside the loop like:

for (i =0; i < plusIcon.length; i  ){
        plusIcon[i].addEventListener("click", function (){
            if (i.classList.contains("fa-plus") {
                icon.classList.remove("fa-plus");
            } else 
                icon.classList.add("fa-minus");
            }                 
    });
}
  • Related