1
votes

With Phoenix live view document I add a live page for writing a realtime form app. There is very simple demo:

<h2>Hello</h2>

Counter is222: <%= @counter %>
<hr>

<button phx-click="dec">-</button>
<button phx-click="inc">+</button>

<table border="1">
  <tr>
    <th contenteditable="true">Month</th>
    <th>S1</th>
    <th>S2</th>
  </tr>
  <tr>
    <td contenteditable="true">January</td>
    <td contenteditable="true">$100</td>
    <td contenteditable="true">$10220</td>
  </tr>
</table>

Server side code (just like document):

defmodule TicTacWeb.MemberSchedulerLive do
  use Phoenix.LiveView


  def render(assigns) do
    TicTacWeb.PageView.render("member_scheduler.html", assigns)
  end

  def mount(_, socket) do
    {:ok, assign(socket, %{counter: 100})}
  end

  def handle_event("inc", _, socket) do
    {:noreply, update(socket, :counter, fn(x) -> x + 1 end)}
  end

  def handle_event("dec", _, socket) do
    IO.puts("item")
    {:noreply, update(socket, :counter, fn(x) -> x - 1 end)}
  end

end

The problem is <td contenteditable value will be revert after I click - or + emit a message to server.

  1. why - or + affect <td>'s value? Is't minimize change modified dom data?
  2. Is there a best practice for such scene?

Thanks!

UPDATE
After add contenteditable as data model, it was still not work, such as:
1. html snippet

    ....
    <td contenteditable="true">$100</td>
    <td contenteditable="true" phx-blur="somedata"><%=@somedata%></td>
  </tr>
</table>
  1. backend
  ...
  def mount(_, socket) do
    {:ok, assign(socket, %{counter: 100, somedata: "$001"})}
  end

The @somedata also revert to $001 if click - or +.

2
Phoenix and LiveView creator Chris McCord discusses using contenteditable with LiveView at: elixirforum.com/t/phx-blur-with-contenteditable/25296/2Mallory-Erik

2 Answers

1
votes

why - or + affect <td>’s value?

It’s vice versa. They do not affect <td>’s value, on the contrary, it sends the diff between the previous state and the updated state and the frontend applies this diff.

LiveView has no idea about your local changes with the contenteditable="true" and hence it resets everything to its original state, save for :counter that gets updated. To support contenteditable="true" you need to make these <td>’s a part of data model so that LiveView is aware about the changes in there.

0
votes

I finally solve the problem by two step:

  1. add phx-update='ignore' and the contenteditable will not be update!
    In this stage, it's <td contenteditable="true" phx-update='ignore'>$10220</td>

  2. update phoenix_live_view to 0.4.1 which was github: phoenixframework/phoenix_live_view(locked commit is: 73e9a695eff1d7d21e4cb34ea9894835b3a2fa32) and the old version seems not support phx-update

Hope it also could be help you.

Thanks @Aleksei Matiushkin, I will dive into liveview diff algorithm.