Phoenix LiveView is now... live!

You can use Phoenix.PubSub (which Phoenix will use by default), if you don’t want to depend on Postgres. Regarding large collections, right now adding a new entry will always reload the whole page but we plan to include mechanisms were you only append/prepend items.

8 Likes

Oh fantastic, thank you!

I’ll definitely take a look at this and it really is time for me to roll my sleeves up and get into Phoenix properly.

1 Like

Just thought I’d try out the rainbow torture test and I’m really impressed. I managed 9 windows, all cranked up to 100FPS before I hit 100% CPU usage on a $5 Digital Ocean droplet. My (high spec) MacBook Pro was having more problems with it than the remote server was.

I think you’d have to have quite a lot of users (when using LiveView as intended) before you’d put some hurt on even a modest dedicated server. Thorughly impressed!

7 Likes

I knew this was going to be a great weekend :partying_face:

2 Likes

I want you to know that I had plans this weekend before this was posted. Know that.

8 Likes

For anyone trying out LiveView, WebSocket felt really slow to connect when I used localhost:4000. It seems that there is some sort of delay at least on Windows. According to this https://stackoverflow.com/questions/15135506/websocket-connection-setup-takes-a-relatively-long-time-is-this-normal it’s caused by IPv6. So if someone is experiencing this as well, use 127.0.0.1:4000 instead.

3 Likes

I asked a question about Optimistic UI 22 days ago, and had a great discussion about the possibilities of achieving it through the use of vanilla JavaScript with Phoenix and/or LiveView, but now when LiveView is released, would you guys please revisit my question and give me some insights about what do you guys think about the possibilities of achieving Optimistic UI with vanilla JavaScript and/or LiveView.

@chrismccord @josevalim @ericmj @Gazler @jeregrine @lance @scrogson @fishcakez @lexmag @whatyouhide @peerreynders @OvermindDL1 @dgmcguire

thank you!

Thank you very much for your response and explaining the current state and direction of LiveView. There’s so much to explore!

It was not my intention to downplay realtime crud forms (or any other goal LiveView is pursuing). On the contrary, I don’t like building and maintaining a JS SPA, LiveView looks like it could be a game-changer.

Perhaps it’s that I see so many possibilities and get so many ideas about this that my thoughts are getting a bit unrestrained and indistinct. As you said: start small and see where things go. :slight_smile:

2 Likes

I think this pattern will be important for LiveView backed forms. From a user point-of-view, losing a bunch of stuff you typed in is a negative experience. However, I’m excited to see what kind of patterns emerge for this.

But while I thinking about this stuff, I’m also not thinking about all the Javascript I would have to write.

I compiled a simple vue component with the webcomponent build target and deployed that within the Demo app web artifacts. In a new LiveView module, I added the custom element markup and socket bindings. Binding the server state into the element works great, i piped in the clock, weather, etc. It works like any other data property and doesnt rerender the entire component.

Unfortunately I spoke a bit too soon. The downside seems to be getting data out of the component. I hacked around the click/submit/change handlers but could not get it to populate the value field of the event passed up the socket. If the wrapper supported CustomEvents (something like. phx-custom-eventname that grabs event.details) then webcomponents could probably work.

Fear not, this is easily doable today :slight_smile:
I have pushed a branch with an example:

Code wise, you can add the dynamic fields with inputs_for like a regular static form:

  <%= label f, :hobbies %>
  <%= inputs_for f, :hobbies, fn hf -> %>
    <%= text_input hf, :title, placeholder: "hobby" %>
    <%= error_tag hf, :title %>
  <% end %>
  <button phx-click="add_hobby">+ Add Hobby</button>

Then in your LV:

  # UserLive.Edit
  def handle_event("add_hobby", _, socket) do
    changeset = Accounts.build_hobby(socket.assigns.changeset, %{title: ""})
    {:noreply, assign(socket, changeset: changeset)}
  end

That’s it! As long as you update your changeset assign, which is what the validate callback does, then there’s no “either/or” dance as the server has the changeset state. My build_hobby code in this case is just a simple ecto embed, but you can get the idea:

  # Accounts
  def change_user(user, attrs \\ %{}) do
    user
    |> populate_hobbies()
    |> User.changeset(attrs)
  end

  defp populate_hobbies(%User{hobbies: []} = user) do
    %User{user | hobbies: [%Hobby{title: ""}]}
  end
  defp populate_hobbies(%User{} = user), do: user

  def build_hobby(changeset, hobby) do
    hobbies = Ecto.Changeset.get_field(changeset, :hobbies)
    Ecto.Changeset.change(changeset, hobbies: hobbies ++ [hobby])
  end

Hope that helps! Here is the branch:

22 Likes

That’s brilliant Chris, thank you! I was thinking about it last night (no computer in front of me) and was going to try something similar. Thanks for the example!

1 Like

Congrats for LiveView great devs! … this seems to be so exciting that if I had the time I was going to start changing lots of JS stuff to it.

However, I am mostly thinking about how to implement the following patterns in LiveView:

  1. Infinite scrolling
  2. Modals/Dialogs
  3. Some material design artifacts such snackbar

I see there is a phoenix_live_view Javascript module with lots of logic in it. Perhaps, if I’m not wrong, the JS architecture can be improved to make it more extensible, by breaking the file into smaller ones so people can reuse parts and add features without having to touch the core …

Anyways, going a little bit deeper, I was reading the morphdom README and found the following sentence:

UPDATE: As of v2.1.0 , morphdom supports both diffing a real DOM tree with another real DOM tree and diffing a real DOM tree with a virtual DOM tree. See: docs/virtual-dom.md for more details.

This makes me think that in the near future, it might be possible to update a React app with content from LiveView.

Finally, I’d like to know if using GraphQL more specifically Absinthe will make sense instead of accessing the backend directly without the extra layer, in case of using plain LiveView without extra Javascript of course.

3 Likes

This looks fantastic. I’ve been waiting to use this in a project of mine. Huge congratulation to the team.

One question - I modified the autocomplete example to return 200 words and on my box the search ground to a bit of a halt - it did eventually return but was taking seconds to display the results. I appreciate returning 200 words isn’t perhaps a real world use case but wondered why the performance loss?

This is amazing, I remember hearing about LiveViews and then watching one of Chris’ video about it a few months ago and that’s one of the reason I started to look more into Phoenix (as a Rails replacement) as I’m looking more into how to reduce the “SPA for everything” trend.

I’ll look into migrating a simple form I have that uses Ajax to LiveView and see how it goes!

I’ve been thinking about contributing to Elixir/Phoenix - are contribution opened yet? How can we jump on the bandwagon and help?

2 Likes

“200 words” is nothing as far as LV is concerned. Consider the rainbow where we are generating 80 divs every 16ms :slight_smile: My hunch is the browser is choking on the <datalist> updates containing 200 options, so my wild guess is it’s a browser issue and nothing in what we’re doing on our side. The datalist thing is somewhat new, so likely not optimized. UX wise, it also doesn’t make sense to render that many options below an input, so the browser’s UI rendering of it is probably not optimized for that case.

2 Likes

Awesome. Let us know how it goes! We tag issues on the phoenix repos as level:starter when they are good opportunities for new folks to get involved without trying to take on the world. We just had our 1.4.2 release so a lot of issues were closed out, but keep an eye on the issue tracker, as this is the best way to get involved. Welcome aboard!

3 Likes

ok, makes sense.

One other question if I may. Is it possible to incorporate LiveView into an existing eex template? I’ve a form which would benefit from typeahead but I’d like to keep the majority of the form in eex with only a specific text box with the typeahead? All the examples seem to isolate the LiveView templates.

1 Like

Yes, see the home page of the examples repo, we have a weather widget on the regular index.htm.eex page.

The form input usecase is a little more complex however, because liveview needs to own the parent form, so in your case, you need to make the entire form the LV template and it will just work via <%= Phoenix.LiveView.live_render(@conn, TypeAheadLive, session: ...) %> in your eex template

1 Like

Perfect - many thanks for your help and the awesome work you’ve done on LiveView and Phoenix.

1 Like