Custom selectors with Hot Controls

When using hot controls it is expected to include data-control="mycontrol" to an element to bind it. Here are some helpful tips for working with this approach.

Binding multiple controls

Did you know you can bind multiple controls to the same element? It works just like a CSS selector! In this example the control1, control2 and control3 controls are all bound to the same DIV element.

<div data-control="control1 control2 control3"></div>

Using a custom selector

Sometimes, you cannot access the element to attach the data-control attribute. In these cases, you can listen to the render event and connect it using JavaScript instead. Here’s a sample code snippet for this:

// This adds data-control="full-calendar" to all elements with .some-class
var mySelector = '.some-class';
var myControl = 'full-calendar';

addEventListener('render', function () {
    document.querySelectorAll(mySelector+':not([data-control~="'+myControl+'"]').forEach((element) => {
        if (element.dataset.control) {
            element.dataset.control = element.dataset.control + ' ' + myControl;
        }
        else {
            element.dataset.control = myControl;
        }
    });
});

Here, we use the data-control~="..." selector to prevent it from adding twice; the ~ modifier checks if the name is found in a space (" ") separated list, just like CSS. Then, we append to that list or start a new list. Hot controls work like magic, so this logic can come any time – before or after the control is registered.

I hope this is helpful to someone out there!

6 Likes

Hey, I love hot controls. I can build a strong & solid vanilla UX with this great feature. I saw that in the documentation, it states you can pass the control name as second optional argument to fetchControl. However, as you can see in line 3788 of this screenshot of framework-extras, it does not take a second argument into account.

Personally, I worked around this by fetching any control and using ControlBase’s context property application to then use the method used in fetchControl; fetch() because it accepts the control name argument.
Ex: oc.fetchControls(‘[data-control]’).pop().context.application.fetch(controlElement, controlName)

I’m just throwing this out there in case somebody else encounters this issue.

1 Like