DaAnalyst

DaAnalyst

Can we get support for colocating shared JS constants with a group of otherwise colocated JS components?

@chrismccord @josevalim @steffend

Been using colocated JS for a while and I keep on stumbling on the same limitation: there is no way (at least known to me) to colocate JS constants with a group of custom elements operating together as a whole (naturally, each defined is in its own file/script module).

I managed to import them (from one script module into another) but they can only be used from connectedCallback on. They don’t exist yet (synchronously) right after the import statement nor can they be used directly or via a function call in the Lit decorators like @provide, @consume and friends, i.e. they cannot be used as constants.

I know it works by simply moving those constants to a .js file and saving it in assets, but that’s no longer a “physical” colocation and those constants are of no concern to the rest of the app.

Is there any chance this could be somehow added to Phoenix/LiveView?

Thanks

Marked As Solved

steffend

steffend

Phoenix Core Team

I see the problem now (note that it would have been much easier if you posted the exact kind of error you’re seeing). Because of the way the JS files are bundled by esbuild, the individual modules are put before the code that initializes the key variables.

The solution to that is to use a different manifest for constants:

  @doc false
  def __colocated_constants__(assigns) do
    ~H"""
    <script :type={Phoenix.LiveView.ColocatedJS} name="SharedFoo" manifest="constants.js">
      const constants = {
        FOO: "foo",
        BAR: "bar",
      }
      export default constants;
    </script>
    """
  end

  def my_component(assigns) do
    ~H"""
    <script :type={Phoenix.LiveView.ColocatedHook} name=".MyHook">
      import constants from "phoenix-colocated/my_app/constants";

      console.log(constants.SharedFoo.FOO);

      export default {
        mounted() {
          this.el.innerText = JSON.stringify(constants.SharedFoo);
        }
      }
    </script>

    <div id="some-id" phx-hook=".MyHook"></div>
    """
  end

Also Liked

steffend

steffend

Phoenix Core Team

You can do something like this:

defmodule MyAppWeb.SomeComponent do
  @doc false
  def __colocated_constants__(assigns) do
    ~H"""
    <script :type={Phoenix.LiveView.ColocatedJS} name="SharedFoo" key="constants">
      const constants = {
        FOO: "foo",
        BAR: "bar",
      }
      export default constants;
    </script>
    """
  end

  def my_component(assigns) do
    ~H"""
    <script :type={Phoenix.LiveView.ColocatedHook} name=".MyHook">
      import { constants } from "phoenix-colocated/my_app";

      export default {
        mounted() {
          this.el.innerText = JSON.stringify(constants);
        }
      }
    </script>

    <div id="some-id" phx-hook=".MyHook"></div>
    """
  end
end

In this example, the constants are available as constants.SharedFoo:

// constants
{"SharedFoo":{"FOO":"foo","BAR":"bar"}}

PS: No need to ping us individually, I’m subscribed to the Proposals section.

steffend

steffend

Phoenix Core Team

Yeah it builds just fine, but I assume you got an exception in the browser like

Uncaught TypeError: can't access property "SharedFoo", imp_mnxw443umfxhi4y is undefined

That would already have put me on the right track :slight_smile:

Anyway, please report back if you find any other issues!

DaAnalyst

DaAnalyst

Yep, it works! Thank you so much for this one. You’ve got a lunch from me if you ever come visit Pula, Croatia (or any other place in the region of Istria).

Last Post!

DaAnalyst

DaAnalyst

Yep, it works! Thank you so much for this one. You’ve got a lunch from me if you ever come visit Pula, Croatia (or any other place in the region of Istria).

Where Next?

Popular in Proposals: Ideas Top

beepboop
(re-post of: Feature idea: measure and expose socket latency · Issue #1890 · phoenixframework/phoenix_live_view · GitHub) This is relate...
New
hst337
Elixir compiler and language specification Purpose of the proposal Elixir language is in mature state and no breaking or heavy changes ar...
New
rmoorman
Current situation Currently, the structure of the HTML returned by phoenix is determined by the layouts (components/layouts/[root,app].ht...
New
superchris
Currently there is no out of the box way to support DOM Custom Events in phoenix. I’ve created a separate library to do this, but I’d lov...
New
pelopo
Hi, Oficial docs got this wonderful feature to download the ePub version that we can chuck to our kindles and read it. Now we are in the...
New
cheerfulstoic
I feel like Elixir is getting big enough and old enough that I’m starting to experience problems with conflicting dependencies. An examp...
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

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31494 112
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40042 209
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
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement