shahryarjb

shahryarjb

Adding Phoenix.LiveView.JS function for getting `getBoundingClientRect` params

When proposing or suggesting something please consider:

As my experience implementing getBoundingClientRect as Phoenix.LiveView.JS function and returns all the parameters of this JS function I mean (height, top, left and etc size) can be help full for complex client side component.

It keeps the ecosystem more clear and integrated. It can prevent the use of other client frameworks or js hook.


For example we have an accordion that is created with Phoenix component and Phoenix.LiveView.JS:

Show or open the accordion:

  def show_accordion_content(js \\ %JS{}, id) when is_binary(id) do
    js
    |> JS.show(to: "##{id}")
    |> JS.show(
      to: "##{id}-content",
      time: 500,
      transition:
        {
           "transition-all transform ease-out duration-300", 
           "will-change-[opacity] opacity-0 h-0",
           "will-change-auto opacity-100 h-[400px]"
        }
    )
  end

As you see I use hard coded height h-[400px] because browsers do not accept transition for h-auto, we have all the commands to open an accordion in Phoenix liveView as you see except some information about the element. It forces me to use hook or something like AlpineJS.

It can be an option for JS.show, JS.hide and (before or after doing operation) etc.

Thank you in advance


Refs:

Most Liked

steffend

steffend

Phoenix Core Team

@garrison already made some very good points. We don’t plan to make complex JS commands.

There are lots of improvements planned for hooks. One of them is to actually expose sticky JS commands like this:

mounted() {
  const js = this.js();
  // js.show, js.hide, js.transition, etc.
  js.toggleClass(this.el, ...);
}

Another big improvement will be colocated hooks that will allow defining the necessary JavaScript next to the components themselves.

garrison

garrison

I did not elaborate because the grid trick in question was linked above :slight_smile: Here is a StackOverflow question with more details:

Honestly you probably could find a way to do it with radio buttons and pure CSS, but I wouldn’t. What I meant was that the animation can all be done with CSS (no JS.transition needed), and then all you need is JS.toggle_class to trigger the CSS animations.

First, you wrap each item in a grid container, and then you use CSS to toggle grid-template-rows between 0fr and 1fr. You set overflow: hidden on the child (the accordion content in your case) so that it’s not visible when closed.

The CSS would look like this:

.container {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 100ms;
}
.container.open {
  grid-template-rows: 1fr;
}

.content {
  overflow: hidden;
}

The HEEx would look like this:

<div>
  <div class="container" phx-click={@open}>
    <div class="content">Foo</div>
  </div>
  <div class="container" phx-click={@open}>
    <div class="content">Bar</div>
  </div>
</div>

And then, if you want all of the other items to close when you open one, you would do this (otherwise you could just use JS.toggle_class("open")):

open =
  JS.remove_class("open", to: ".container.open")
  |> JS.add_class("open")

This is just a minimal demonstration of the mechanism, obviously you would also need some sort of title for each item to actually click on :slight_smile:

garrison

garrison

The code I’ve written to get around this issue (using the liveSocket to trigger JS commands in data- attributes) is some of my least favorite in my app - it’s obviously suboptimal. I think opening up the sticky API is inevitable, and I don’t see any obvious problems (it’s the same thing we’re already doing anyway, just directly). I would imagine the work simply hasn’t been done yet - JS commands are still relatively new and improving quickly. We only just got toggle_class, which was a big improvement :slight_smile:

Where Next?

Popular in Proposals: Ideas Top

mythicalprogrammer
Hello, since the 1.8rc0 was out, DaisyUI was noted to have the benefit of light and dark mode. From the elixir subreddit, it seem a few ...
New
DaAnalyst
@chrismccord @josevalim @steffend Been using colocated JS for a while and I keep on stumbling on the same limitation: there is no way (a...
New
jakeprem
Goal: To make JS.patch and JS.navigate more interoperable with JS.push. Scenario: Imagine making a reusable Phoenix component and you wa...
New
manhvu
In a large repo, working with module need to add alias too much is quite annoyed and not good for organizing code. I think better add su...
New
cevado
IEx is a very powerfull shell and it would be awesome to have all this power integrated inside a code editor. Clojure enables something l...
New
pejrich
I propose adding compact_map/2 to the Enum module. What is it? Sometimes you want to map over a collection, but sometimes you want to ma...
New
spicychickensauce
I’ve previously explored what is possible today with hacks to implement view transitions in our apps: I have since created a fork to im...
New
i-n-g-m-a-r
When debug_errors: true javascript can be executed. &lt;html&gt; &lt;body&gt; &lt;form id="xss" action="https://domain.com/NateMai...
New
c4710n
This is an idea for improving the workflow of iex -S mix phx.server The Problem and The Solution in use When running multiple Phoenix en...
New
sevensidedmarble
I have a very simple suggestion: the generated config/dev.exs file should read from PORT at compile time to set the endpoints port. If ...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42842 311
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement