javascripthtmleventsevent-handlingdom-events

How to listen for close event of datetime-local in pure JavaScript?


I have an input of type datetime-local where the text field is hidden and showPicker() is used to open the browser interface for the picker GUI. showPicker() is triggered via an onclick event of a custom calendar icon. What I want is to run a function when the picker is closed.

I know that you can do this in jQuery via onClose on their Datepicker widget, but my project does not use jQuery and I am not interested in adding that framework dependency.

The onclose event does not trigger when the datetime-local element loses focus, due to the picker being in the shadowDOM and not the regular document hierarchy. The onblur and onfocusout did not work either.

Here is a minimal example of what I want to see trigger:

const picker = document.getElementById("datePicker");
const icon = document.querySelector("img");    

icon.onclick = function() {
  picker.showPicker();
};

picker.onclose = function() {
  alert("This does not work!");
};

picker.onblur = function() {
  alert("This does not work either!");
};

picker.addEventListener("focusout", (event) => {
  alert("Neither does this!");
});
#datePicker {
  width: 1px;
  height: 1px;
  border: none;
}

img {
  width: 32px;
  height: 32px;
  cursor: pointer;
}
<img src="https://static.vecteezy.com/system/resources/previews/002/387/838/original/calendar-icon-flat-style-isolated-on-white-background-free-vector.jpg" />
<input id="datePicker" type="datetime-local" />

It doesn't work on Stack Overflow or JSFiddle due to the SecurityError about a cross-origin iframe, so to view the code in action you will likely need to run it locally.


Solution

  • I was able to get this working by using the onchange event, but it only works when the user actually interacts with the popup. If they click the default selected date (today) then it functions fine, but if they just leave it selected and close the popup then it doesn't work.

    See example code below:

    const picker = document.getElementById("datePicker");  
    
    picker.onchange = function() {
      alert("This works when the input is changed, but not when the picker is closed without user interaction.");
    };
    

    This is more of a workaround than the actual solution I was looking for, so other answers are welcome.