Holiday Notice: Support will be provided on a limited scale from December 24th, 2024, to January 2nd, 2025. Happy holidays and a wonderful New Year!


Topic: Hooking MDB Select's Focus Event

Neil Cresswell priority asked 1 year ago


We're trying to hook the focus event for a select field. Specifically this is the focus event, not the click or touch events, since we want to fire some code when the field comes into focus. (Say the user is tabbing through a form for example rather than clicking or touching fields.)

Normally we can use an onfocus="" attribute in the HTML or add a focus event listener via JS. Those methods work well for text field inputs while using MDB. However with the MDB Select in particular, the <select> element is replaced "under the hood" by MDB which uses a different input, so we can't for example embed an onfocus in our HTML. I do see there are some helpful custom event hooks you're providing for folks trying to hook MDB's select: https://mdbootstrap.com/docs/standard/forms/select/#docsTabsAPI

We experimented with those and can get shown.mdb.select and open.mdb.select to both fire when an MDB select is clicked, but we've been unable to find a hook that works for when the select field is focused by tabbing around.

Q1: Please can you point us at the correct method to hook the focus event on an MDB select element? If that doesn't exist, possibly it might be helpful to add custom events for focus and blur. Just a thought! Many thanks in advance for looking at this for us. Hopefully we're just missing something obvious here.

Q2: I'm also wondering why there is both a shown.mdb.select and open.mdb.select, since they seem to fire for the exact same circumstances? Is it possible you meant the former to be for when MDB select has finished initializing so it fires at the point where the select field has finished being replaced? Selects in forms can look pretty ugly until the MDB JS code has had a chance to load, which may take a while on a slow connection, so knowing when the JS has finished rendering would be quite useful.


Neil Cresswell priority answered 1 year ago


@kpienkowska: Thanks for sharing the code snippet and the follow-up reply.

I'd already tried essentially the same thing on a select before pinging you, but this didn't work:

document.querySelectorAll('#registrationForm input.select-input').forEach((element) =>
{
    element.addEventListener('focus', (event) =>
    {
        console.log(event);
    });
});

i.e. Take our form and add focus event listeners on all of the inputs that have the .select-input class, which is one added by MDB in the main DOM for an MDB select.

On top of that, for test purposes I had also a bit of a temporary fudged wrapper around the above to add the event listener only after allowing sufficient time for MDB's deferred JS to load and create the replacement inputs, which can take a few seconds if the client's Internet speed is slow.

With the fudge in place, the elements were found and the event hooked but would never fire. Possibly this is because instead of the added input getting the focus, a shadow root div beneath the new input may be getting the focus instead, and AFAIK focus events don't bubble up/cascade.

Rather than worrying about the shadow root element, as an alternative approach I eventually looked at delegated events on the entire form. This is also a better solution because it avoids our fudged wrapper since we don't have to wait for MDB to finish setting up the replacement inputs. For that we can use focusin events instead, which do bubble up/cascade. I finally found a solution which worked for us so sharing here in case it helps someone else:

document.getElementById('registrationForm').addEventListener('focusin', (event) =>
{
    if (event.target.classList.contains('select-input'))
    {
        console.log(event.target); // do stuff
    }
});

Similarly, for someone looking for a blur event on an MDB Select, they can possibly use focusout if there isn't something more suitable.


Kamila Pieńkowska staff commented 1 year ago

I'm sorry but I don't know if there is a question somewhere in your reply. Do you need further help?


Neil Cresswell priority commented 1 year ago

No, but thank you. I just wanted to share the solution we came up with as you can't hook a focus event for an MDB select, in case it's helpful for others. We can close this now.


KieranFoot free commented 1 year ago

You can also access the element directly through the Select control via _input.


KieranFoot free answered 1 year ago


A quick look through the select source code would lead you to internal elements used by select to render the select you see as opposed to the original which is hidden.

Then you can hook the events of those elements.

I doubt they will add a myriad of extra events to support non standard usages, so you will need to take a non standard approach. Of course this has the downside of; If they change their internal API, your code breaks. But having spent some time looking through the MDB code and modifying/upgrading it a lot, it does follow a pretty standard layout, so I don't think the internal API should change dramatically.


Kamila Pieńkowska staff answered 1 year ago


Q1: I'm not sure what you need this focus for so I don't really know what I can advise you. Without this, I can only suggest adding a listener to the input created by a select component during initiation.

Q2: open event fires when the open method is used and listening to it allows you to use preventDefault. The shown event fires when the select dropdown animation finishes. So they fire around 200ms apart and can be useful for different purposes.


Neil Cresswell priority commented 1 year ago

Q1:

I'm not sure what you need this focus for so I don't really know what I can advise you.

Imagine someone using the tab key on a keyboard or next field key on a mobile device to move around a form of input fields and selects. We want some code to fire when a particular mdb select receives the focus.

I can only suggest adding a listener to the input created by a select component during initiation.

That was the first thing we tried once, unfortunately without much luck.

Please can you give us an example how to hook a focus event for when an MDB select field gets the focus?

Q2: Thanks for the explanation. Makes sense.


Kamila Pieńkowska staff commented 1 year ago

For component needs we monitor focus of created input. Here is how you can do that too: https://mdbootstrap.com/snippets/standard/kpienkowska/5433571#js-tab-view


FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Closed

Specification of the issue

  • ForumUser: Priority
  • Premium support: Yes
  • Technology: MDB Standard
  • MDB Version: MDB5 6.4.0
  • Device: Desktop
  • Browser: Chrome
  • OS: Linux
  • Provided sample code: Yes
  • Provided link: Yes