Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rawilk's avatar
Level 47

Alpine custom magic not accessible in x-show

I have a custom magic for a custom dropdown I'm making called $option. This magic allows me to determine certain states of the option. Here is a brief overview of the magic:

Alpine.magic('option', el => {
    let data = Alpine.$data(el);
    let optionEl = Alpine.findClosest(el, i => i.__optionKey);

    ....

    return {
        get isExpanded() {
             console.log('called');
             return data.__context.isExpandedEl(optionEl);     
        };
    };
});

The magic works fine in most cases, except when I'm trying to use it in certain Alpine directives, such as x-show or :class. For some reason, the method doesn't even seem to be firing in those contexts.

If I do something like this in the component, the magic's getter is called, and I see the console log:

<span x-text="JSON.stringify($option.isExpanded)"></span>

However, if I do this, nothing happens and I never see the console log from the getter:

<span x-show="$option.isExpanded"></span>
0 likes
2 replies
LaryAI's avatar
Level 58

It looks like the issue might be related to the order in which Alpine evaluates directives. In some cases, directives like x-show are evaluated before custom magic is initialized, which means that the magic isn't available yet.

One solution to this problem is to use the x-data directive to initialize your component and make sure that the custom magic is available before any other directives are evaluated. Here's an example:

<div x-data="{ $option: $option }">
  <span x-show="$option.isExpanded"></span>
</div>

In this example, we're using the x-data directive to create a new Alpine component and pass in the $option object as a property. This ensures that the custom magic is available before any other directives are evaluated.

Note that we're wrapping the x-show directive in a div element. This is because the x-data directive needs to be attached to an element in order to work properly. If you don't want the div element to affect your layout, you can use CSS to hide it:

<div x-data="{ $option: $option }" style="display: none;">
  <span x-show="$option.isExpanded"></span>
</div>

This will ensure that the div element is hidden, but still allows the x-data directive to work as expected.

I hope this helps! Let me know if you have any questions.

rawilk's avatar
rawilk
OP
Best Answer
Level 47

I've found what the issue is I think. I didn't realize the element I was using the magic on was outside of the scope of the element that $option is attached to.

Please or to participate in this conversation.