I display a dropdown menu if the user clicks on some icon.
Any pointers on how to close that dropdown when the user clicks outside of it?
I would suggest not using liveview for interactions like opening/closing dropdowns in the first place. liveview is great for interactions, which need to contact the server anyways, but for pure client side interactions it’s better to keep things fast and without latency. The simplest way to do this is currently alpine.js, which can be easily integrated with liveview to not lose its state when liveview issues updates to the markup. Alpine also has examples of doing exactly those “click elsewhere” events you need for dropdowns and similar components.
1 Like
I’m reopening this thread as Phoenix.LiveView.JS
is now a thing
Is there any built-in feature in LiveView.JS
similar to AlpineJS click outside ?
1 Like
phx-click-away
was added in 0.17 (October 2021) as part of this PR:
phoenixframework:master
← phoenixframework:cm-cmds
opened 06:14PM - 07 Oct 21 UTC
This PR provides commands for executing JavaScript utility operations on the cli… ent with an extended push interface to clean up the number of `phx-` bindings while supporting long requested features.
Closes #1494, Closes #554, Closes #669, Closes #551.
JS commands support a variety of utility operations for common client-side needs, such as adding classing, showing or hiding content, and transitioning in and out with animations. While these operations can be accomplished via client-side hooks, JS commands are DOM patch aware, so operations applied by the JS APIs will stick to elements across patches from the server.
In addition to purely client-side utilities, the JS command incluces a rich `push` API, for extending the default `phx-` binding pushes with options to customize targets, loading states, and additional payload values.
## Enhanced Push Events
The `push/3` command allows you to extend the built-in pushed event handling when a `phx-` event is pushed to the server. For example, you may wish to target a specific component, specify additional payload values to include with the event, apply loading states to external elements, etc. For example, given this basic `phx-click` event:
<div phx-click="inc">+</div>
Imagine you need to target your current component, and apply a loading state to the parent container while the client awaits the server acknowledgement:
<div phx-click={JS.push("inc", loading: ".thermo", target: @myself)}>+</div>
This also allows you to supply different targets for each binding, as requested in #1494, #554, #669, #551:
<.form for={@changeset}
phx-change={JS.push("validate", target: @myself)}
phx-submit={JS.push("save"}>
Push commands also compose with all other utilities. For example, to add a class when pushing:
<div phx-click={
JS.push("inc", loading: ".thermo", target: @myself)
|> JS.add_class(".warmer", to: ".thermo")
}>+</div>
## Client Utility Commands
The following utilities are included:
* `add_class` - Add classes to elements, with optional transitions
* `remove_class` - Remove classes from elements, with optional transitions
* `show` - Show elements, with optional transitions
* `hide` - Hide elements, with optional transitions
* `toggle` - Shows or hides elements based on visiblity, with optional transitions
* `transition` - Apply a temporary transition to elements for animations
* `dispatch` - Dispatch a DOM event to elements
For example, the following modal component can be shown or hidden on the client without a trip to the server:
```elixir
def hide_modal(js \\ %JS{}) do
js
|> JS.hide(to: "#modal", transition: "fade-out")
|> JS.hide(to: "#modal-content", transition: "fade-out-scale")
end
def modal(assigns) do
~H"""
<div id="modal" class="phx-modal" phx-remove={hide_modal()}>
<div
id="modal-content"
class="phx-modal-content"
phx-click-away={hide_modal()}
phx-window-keydown={hide_modal()}
phx-key="escape"
>
<button class="phx-modal-close" phx-click={hide_modal()}>✖</button>
<p><%= @text %></p>
</div>
</div>
"""
end
```
This PR also includes a few other new features:
- The addition of the `phx-click-away` binding for handling an element losing click "focus", or being clicked away from, such as toggled drop downs, modals, etc
- The addition of a new `phx-remove` binding for handing an element being removed from the DOM, for example to trigger an animation
- The `:loading` option which gives the ability to specify additional selectors to receive a `phx-[event]-loading` class while awaiting a server acknowledgement from a push. These elements will also receive a ref and be locked for in flight updates until the ack comes back
- The ability to pass payload values to push instead of embedded them in the DOM via `phx-value-` attributes, which requires parsing values back from strings
7 Likes
Perfect!
not my thread so I cannot acknowledge the solution