Search code examples
javascriptajaxpreventdefault

Js Vanilla dynamic url + nesting anchor and preventdefault


How to preventdefault anchor that has child element. I use event delegate click since the link is set dynamically.

When user click, I have to check if it has data-applink in the anchor, in this case I traverse using closest to find its parent (since click event will detect child element, not the anchor).

After I obtain the parent, then I add click event and preventdefault it. But somehow it does not work.

Please help, any idea?

//simulate ajax
setTimeout(()=> {
  const anchor = document.querySelectorAll('.anchor')[0];
  anchor.setAttribute("href", "http://www.google.com");
  anchor.setAttribute("data-applink", "app://link.id");
},800);

const checkNesting = (selector, event, callback) => {
  let elem = event.target;
  if (elem.matches(selector)) {
     callback(elem);
  }else{
     elem = event.target.closest(selector);
    if (elem) {
      // console.log(elem);
       callback(elem);
    }
  }
 

}
document.body.addEventListener('click', (event) => {
  checkNesting('*[data-applink]', event, (el) => {
    el.addEventListener('click', (ev) => {
       ev.preventDefault();
    });
  });
});
<a href="#" class="anchor">
  <button>Click Here</button>
</a>


Solution

  •     el.addEventListener('click', (ev) => {
           ev.preventDefault();
        });
    

    My best guess is that the above event listener starts working at the next click event, not the current one. If anyone can provide explanation, I am very appreciated.

    To solve your problem, you can apply preventDefault to the current event:

    //simulate ajax
    setTimeout(()=> {
      const anchor = document.querySelectorAll('.anchor')[0];
      anchor.setAttribute("href", "https://www.google.com");
      anchor.setAttribute("data-applink", "app://link.id");
    },800);
    
    const checkNesting = (selector, event, callback) => {
      let elem = event.target;
      if (elem.matches(selector)) {
         return true
      }
      elem = event.target.closest(selector);
      if (elem) {
        // console.log(elem);
         return true
      }
      return false
    }
    document.body.addEventListener('click', (event) => {
      if (checkNesting('*[data-applink]', event)) {
        event.preventDefault();
      }
    });
    <a href="#" class="anchor">
      <button onClick="alert('I am working fine and bubbling up is cancelled')">Click Here</button>
    </a>
    
    <a href="https://www.google.com">
    <button onClick="alert('I allow bubbling up')">Click me too</button>
    </a>