Mizushima Hideyoshi
Mizushima Hideyoshi

Reputation: 49

Uncaught TypeError: Cannot read property 'parentElement' of undefined

I found a lot of answered questions similar to my question yet all of those, the elements are actually "undefined". In my case, it exists.

My code works as expected. Basically it's adding eventListener to all modal-dismiss button which is an anchor. The closing function is to find the outer most modal div and give it "hidden" class which set its display to none.

It closes the modal correctly but after the modal is closed, that error show up.

const bookBTN =             document.getElementById('bookBTN');
const apptModalStart =      document.getElementById('appt-start');
const apptModalEnd =        document.getElementById('appt-end');
const apptStartContent =    apptModalStart.querySelector('.appt-content');
const apptEndContent =      apptModalEnd.querySelector('.appt-content');
const modalCloseBTNs =      document.querySelectorAll('.modal-dismiss');

for(let i = 0; i < modalCloseBTNs.length; i++) {
    modalCloseBTNs[i].addEventListener('click', function(e) {
        closeAppointmentWindow(modalCloseBTNs[i]);
    })
}

const closeAppointmentWindow = (btn) => {
    let parent = getClosestParentByClass(btn, "appt-modal");  // Line 52
    parent.classList.add('faded');
    if(parent === apptModalStart) showBTN(bookBTN);
    setTimeout(function() {
        parent.classList.add('hidden');
    }, 300);
}

const getClosestParentByClass = (e, parentClass) => {
    let parent = e.parentElement;  // Line 61
    if(e.parentElement.classList.contains(parentClass)) return parent;
    else return getClosestParentByClass(parent, parentClass);
}

appointments.js:61 Uncaught TypeError: Cannot read property 'parentElement' of undefined

at getClosestParentByClass (appointments.js:61)

at closeAppointmentWindow (appointments.js:52)

at HTMLDivElement. (appointments.js:30)

Please give me some insight as to why it is giving me that error.

Edits: I have already console.log(modalCloseBTNs), console.log(modalCloseBTNs[i]) in the loop, console.log(e) and console.log(btn) respectively in each function and they are all defined. Except for btn and e, they shows 2 versions each, one is defined the 2nd one right after the function finished (which is hinting that it runs 2 times??? for some reason) that is undefined.

Upvotes: 0

Views: 9544

Answers (1)

epascarello
epascarello

Reputation: 207557

You are going to run into an element up the chain with no parent, you assume it always will have one

const getClosestParentByClass = (e, parentClass) => {
  let parent = e.parentElement;  // Line 61
  if(!parent) return null;
  else if(e.parentElement.classList.contains(parentClass)) return parent;
  else return getClosestParentByClass(parent, parentClass);
}

In the end you are reinventing closest()

const elem = btn.closest(".appt-modal")

Upvotes: 1

Related Questions