How to convert old liveview app to new Phoenix version?

Background

I am in the process of porting an old LiveView app to the newest version of Phoenix ( v1.6.5). Being new to the whole thing in general I was expecting to run mix phx.new web_interface --live --no-ecto and to the find a similar structure to what I had before:

├───assets
│   ├───css
│   ├───js
│   └───static
│       └───images
├───config
├───lib
│   ├───web_interface
│   └───web_interface_web
│       ├───channels
│       ├───live
│       ├───templates
│       │   └───layout
│       └───views
└───priv
    └───static
        └───assets

Instead I got:

├───assets
│   ├───css
│   ├───js
│   └───vendor
├───lib
│   └───web_interface
│       ├───controllers
│       ├───templates
│       │   ├───layout
│       │   └───page
│       └───views
└───priv
    ├───gettext
    │   └───en
    │       └───LC_MESSAGES
    └───static
        ├───assets
        └───images

Something is missing

Paying close attention you will now see I am missing a couple of important folders, namely, web_interface_web and the live folder.

So now I am understand the impression I either missed a huge milestone upgrade or that something is wrong with my mix phx.new command.

Questions

  • Why are these folders missing?
  • How can I port the project? What are the equivalent folders now?

It’s the new structure…

no more assets/static, since You don’t use webpack, and no more copy-webpack-plugin
→ just put manually in priv/static
no live folder, until You use mix phx.gen.live
→ You can do it in a fresh Phoenix project, use mix phx.gen.live, and You’ll have a live folder
no need to pass live to phx.new, it is not needed anymore
→ It’s the default now, mix help phx.new will show You the available options

This app is an umbrella app. This is why I used the previously mentioned command. Was I wrong to use it?
Will this new structure play nice with umbrella projects? (Do I need to do any additional tweaks?)

I don’t think it’s that different between an umbrella, and not an umbrella.

Mostly, it will change your mix file to point to the root of the umbrella, like this…

  def project do
    [
      ...
      build_path: "../../_build",
      config_path: "../../config/config.exs",
      deps_path: "../../deps",
      lockfile: "../../mix.lock",
      ...
    ]
  end

So if I understand correctly:

  • I create a normal phoenix app inside my umbrella via mix phx.new.web APP [--module MODULE] [--app APP]: mix phx.new.web — phx_new v1.7.10
  • Then I go inside the newly created folder and run mix phx.gen.live

And then in theory, I get a Phoenix LiveView app.
There is one problem though:


mix phx.gen.html, phx.gen.json, phx.gen.live, and phx.gen.context
expect a context module name, followed by singular and plural names
of the generated resource, ending with any number of attributes.
For example:

    mix phx.gen.html Accounts User users name:string
    mix phx.gen.json Accounts User users name:string
    mix phx.gen.live Accounts User users name:string
    mix phx.gen.context Accounts User users name:string

The context serves as the API boundary for the given resource.
Multiple resources may belong to a context and a resource may be
split over distinct contexts (such as Accounts.User and Payments.User).

None of this was needed when I first started the old version of the project. I have a feeling there has been a major shift in paradigm here. I don’t understand what I am being asked.

Do you recommend any resources that can walk me through the new version?

Does anyone know if this course is updated enough that the Phoenix part is uppar with 1.6.5?

mix phx.gen.live needs parameters… for example, as mentionned in the help.

mix phx.gen.live Accounts User users name:string age:integer

It might not be scientific, but I always try to run commands in a demo application before I run in dev application.

The result is a live folder, with live_helpers.ex inside…

I’ll show the one generated for me.

defmodule MyappWeb.LiveHelpers do
  import Phoenix.LiveView
  import Phoenix.LiveView.Helpers

  alias Phoenix.LiveView.JS

  @doc """
  Renders a live component inside a modal.

  The rendered modal receives a `:return_to` option to properly update
  the URL when the modal is closed.

  ## Examples

      <.modal return_to={Routes.admin_user_index_path(@socket, :index)}>
        <.live_component
          module={TwixWeb.UserLive.FormComponent}
          id={@user.id || :new}
          title={@page_title}
          action={@live_action}
          return_to={Routes.admin_user_index_path(@socket, :index)}
          user: @user
        />
      </.modal>
  """
  def modal(assigns) do
    assigns = assign_new(assigns, :return_to, fn -> nil end)

    ~H"""
    <div id="modal" class="phx-modal fade-in" phx-remove={hide_modal()}>
      <div
        id="modal-content"
        class="phx-modal-content fade-in-scale"
        phx-click-away={JS.dispatch("click", to: "#close")}
        phx-window-keydown={JS.dispatch("click", to: "#close")}
        phx-key="escape"
      >
        <%= if @return_to do %>
          <%= live_patch "✖",
            to: @return_to,
            id: "close",
            class: "phx-modal-close",
            phx_click: hide_modal()
          %>
        <% else %>
         <a id="close" href="#" class="phx-modal-close" phx-click={hide_modal()}>✖</a>
        <% end %>

        <%= render_slot(@inner_block) %>
      </div>
    </div>
    """
  end

  defp hide_modal(js \\ %JS{}) do
    js
    |> JS.hide(to: "#modal", transition: "fade-out")
    |> JS.hide(to: "#modal-content", transition: "fade-out-scale")
  end
end

Just copy this file in live.

@kokolegorille I apologize if my question was not well formulated. I understand the command needs parameters and that a live folder is created.

What I don’t understand is the semantic meaning of the parameters and their implications in the new app. For example, does this mean my new live view app needs to be divided into models or subjects? in the previous version my app was not divided into this schema.

This is also why I was hoping if you knew any good courses for the new version. At this point, simply copy-pasting my old app would not do, as it won’t fit the new format.

this site may help you

2 Likes