LiveView.JS.toggle for setting aria attributes on dropdowns?

Hi, I’ve some older Tailwind/Alpinejs that I’m trying to migrate to use the new LiveView.JS javascript code. If you check out the various tailwind examples, they demonstrate that AlpineJs can be used to bind dom attributes to a state variable, eg you can have an aria-expanded=true or an aria-hidden=true, etc, and that can follow the state variable bound to that section

I’m wondering how I might simulate this with LiveView.JS? The examples which seem tricky are fold/unfold side menus and dropdown profile/menu links. In both cases the original component is functioning like a toggle, but the LiveView.set_attribute/remove_attribute functions don’t seem to work within the toggle functionality?

I guess it could work to have some kind of “if” functionality? Or if the JS.set_attribute could reference and read the current state and apply a function?

I think it could be done by catching the show/hide events that phoenix generates, but that seems like a lot of extra typing and complex code flow…

(Although I’m also reading the description of when one needs to set aria-hidden, etc and perhaps tailwind examples are setting it excessively anyway? display:hidden seems enough for visual and screen-readers?)

I don’t think that it is currently possible.
You either have to remove the aria-expanded completely or you could keep track of the state in your LiveView with something like this:

<button phx-click={
  JS.set_attribute({"aria-expanded", !@expanded}, to: "#side-menu") 
  |> JS.push("side-menu-toggled", value: %{expanded: !@expanded})
}>Toggle</button>

and then handle the side-menu-toggled in your LiveView.

Or you write some custom JavaScript (where you keep track of your menu state) and use JS.dispatch.

2 Likes

Thanks. I think it’s the .push() call which gives me some insight on how to handle this more widely. I could (for example) use this to track current state of side menus being folded/unfolded so that they stay set between redirects. Very interesting. Thanks

1 Like

I wonder if @chrismccord might consider a feature request here. Immediately after writing the above, I found myself wanting to do a class toggle which doesn’t actually make an item disappear, but merely toggle CSS classes, either on this item or another item?

So something like clicking on a button adds a class to make it look highlighted, and again de-highlights it. Or a sidebar menu gets a highlight when clicked and unfolded. Or specifically, on a dropdown, I wanted a triangle to appear to animate 90 degrees as I clicked to unfold the dropdown.

I can definitely do it with the roundtrip to the server as you showed, but I wonder if others feel a usecase for something like JS.toggle_class() which doesn’t actually disappear the item, only add/remove some classes as you keep clicking?