English 中文(简体)
如何从@form 内容中填满国际交易日志
原标题:How to populate UI from @form content

I am new to LiveView, Phoenix and Elixir, and I am struggling to populate the UI from the form content. Here s a simplified version of what I have in my code: I have defined a struct with some simple fields:

defmodule MyApp.MyStruct do
  defstruct some_integer: 3,
            some_string: "",
            some_bool: true
end

然后,我有以下背景:

defmodule MyApp.Context do
  alias MyApp.MyStruct

  def current_struct() do
    %MyStruct{}
  end
end

It simply returns the newly created struct with default values. I will implement modifying later. Now, I need to display a form populated with these values + allow modifying them. This is my _live.ex file:

defmodule MyAppWeb.ViewLive do
  alias MyApp.MyStruct
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, form: to_form(Map.from_struct(Context.current_struct())))}
  end

  # Here I have handle_event methods, but they don t do anything at the moment.
end

最后,这是<代码>。

<div class="container mx-auto my-4">
  <.form for={@form} phx-change="change_form" phx-submit="submit_form">
    <!-- Number picker -->
    <div class="mb-4">
      <.label>I want to pick a number here:</.label>
    </div>
    <div class="flex items-center space-x-4 mb-4">
      <label class="cursor-pointer">
    <input type="radio" name="some_integer" value="3" class="hidden" checked={Context.current_struct().some_integer == 3}
    />
        <span class={"px-4 py-2 rounded-md #{if Context.current_struct().some_integer == 3, do: "bg-gray-400", else: "bg-gray-200"} hover:bg-gray-400"}>
          3 of something
        </span>
      </label>
      <!-- More of these integer options -->

    <!-- Checkbox -->
    <div class="mb-4">
      <.input
        label="I d like this to be true or false:"
        type="checkbox"
        value={Context.current_struct().some_bool}
        field={@form[:some_bool]}
      />
    </div>

    <.button>Submit</.button>
  </.form>
</div>

The code above kind of works now for initial values, but it stops working when I select 7 or 10 instead of 3. Note how to get the value or compute background colours I use Context.my_struct() for calculations. I assume, that if I implement handle_event("change_form"...) and modify my current_struct() on each change, then the change would also be applied on UI. But I would like to modify the actual struct only on submit, and in the meantime to get the data from the @form. I tried to do that, but failed.

当我试图做这样的事情时

value={@form[:some_bool]}

然后它坠毁。 当我尝试使用<代码>input_ Value()时,我总是拿到零件,即使<代码>inspect(form)<代码>显示,s_integer <>/code>和s_bool/code>。 我期望它们有价值。

请告诉我,我如何能够做到这一点。

问题回答

I assume, that if I implement handle_event("change_form"...) and modify my current_struct() on each change, then the change would also be applied on UI. But I would like to modify the actual struct only on submit, and in the meantime to get the data from the @form

在<代码>()中,你可以从你的结构中提取这些数值,并将这些数值储存在册,然后这些数值可用于填入<编码>。 在用户对表格进行改动后,将打电话到handle_event(>,handle_event()将接受表格中所用的数值。

In addition, inside mount() you can save your original struct in the socket, then in handle_event() you will be able to access any values from the struct that you need. After the user hits Submit, handle_event() will receive the final values entered into the form, which you can use to update the original struct.

例如:

#=========  Your struct code =======

defmodule MyApp.MyStruct do
  defstruct some_integer: 3,
            some_string: "",
            some_bool: true
end

defmodule MyApp.Context do
  alias MyApp.MyStruct

  def current_struct() do
    %MyStruct{}
  end
end

#================================

defmodule DemoWeb.DemoLive do
  use DemoWeb, :live_view

  def mount(_params, _session, socket) do
    orig_struct = MyApp.Context.current_struct()
    o_int = orig_struct.some_integer
    o_string = orig_struct.some_string
    o_bool = orig_struct.some_bool

    initial_form_data = %{
      "input_int" => o_int,
      "input_string" => o_string,
      "input_bool" => o_bool
    }

    socket = assign(socket,
        my_struct: orig_struct,
        current_int: o_int,
        current_string: o_string,
        current_bool: o_bool,
        my_form: to_form(initial_form_data)
      )

    {:ok, socket}
  end

  def render(assigns) do

    # When you write:
    #
    # <.form for={@my_form} ... >
    #   <.input  field={@my_form[:input_int] } ... />
    #
    # that creates an input element with the type atribute set to "text",
    # the name and id attributes set to "input_int", and the value
    # attribute set to the value corresponding to the "input_int" key in the form data
    # given to to_form().  If there s no key for "input_int" in the form data, then there
    # won t be a value attribute--unless you explicitly set the value attribute.  Explicitly
    # setting the value attribute takes precedence over any form data given to to_form().
    #

    ~H"""
    <div>
      <%= "current integer: #{@current_int}, current string: #{@current_string},
           current bool: #{@current_bool}"  %>
    </div>
    <div>
    <%= "original integer: #{@my_struct.some_integer}, original string: #{@my_struct.some_string},
           original bool: #{@my_struct.some_bool}"  %>
    </div>
    <div>-------</div>
    <div>-------</div>


    <.form for={@my_form} phx-change="changed" phx-submit="save">
      <.input label="Some integer:"
              field={@my_form[:input_int] } 
              value={@current_int}
      />
      <.input label="Some string:"
              field={@my_form[:input_string]} 
              value={@current_string}
      />
      <.input label="Some bool:"
              field={@my_form[:input_bool]}
              value={@current_bool}
      />
      <.button>Submit</.button>
    </.form>
    """
  end

  def handle_event("changed",
                   %{"input_int" => entered_int,
                     "input_string" => entered_string,
                     "input_bool" => entered_bool
                    },
                  socket) do

    #Do something with entered_int, entered_string, entered_bool, e.g. change
    #the values that the <div> uses:
    socket = assign(socket,
                    current_int: entered_int,
                    current_string: entered_string,
                    current_bool: entered_bool
              )

    {:noreply, socket}
  end

  def handle_event("save",
                   %{"input_int" => entered_int,
                     "input_string" => entered_string,
                     "input_bool" => entered_bool
                    },
                   socket) do

    start_struct = socket.assigns.my_struct
    updated_struct = %{start_struct | some_integer: entered_int,
                                      some_string: entered_string,
                                      some_bool: entered_bool}
    #Do something with updated_struct, e.g.:
    IO.inspect(updated_struct, label: "[ME]updated struct:")

    {:noreply, socket}
  end


end

这里是活语页面所看的例子:


“enterography

在模板中撰写:

field={@my_form[:input_int]

本职能定义:

 def handle_event("save",
                   %{"input_int" => entered_int,
                     "input_string" => entered_string,
                     "input_bool" => entered_bool
                    },
                   socket) do

pattern/em>。 • 绘制地图,如:

iex(2)> function_argument = %{"a" => 10, "b" => 20}
%{"a" => 10, "b" => 20}

iex(3)> %{"a" => a_val} = function_argument
%{"a" => 10, "b" => 20}

iex(4)> a_val
10

iex(5)> %{"b" => b_val, "a" => a_val} = function_argument
%{"a" => 10, "b" => 20}

iex(6)> b_val
20

iex(7)> a_val
10

你们也可以这样做:

 def handle_event("save", payload, socket) do

   %{"input_int" => entered_int,
     "input_string" => entered_string,
     "input_bool" => entered_bool} = payload
               

该法典:

updated_struct = %{start_struct | some_integer: entered_int,
                                  some_string: entered_string,
                                  some_bool: entered_bool}

利用special syntax,用于更新地图或结构(如用于清单的Syntax)。 特别辛迪加确保这些钥匙已经列入地图,因此,错失行为不会给地图增添新的钥匙。

Watch the output in a terminal window, and you ll be able to see what happens when you change an input field or hit the Submit button.

When I try to use input_value(), then I always get nil, even if inspect(form) shows that both some_integer and some_bool have the values that I expect them to have.

我获得的唯一途径是<代码>nil。 我请我发言:

Phoenix.HTML.Form.input_value(my_form, :input_int)

如果钥匙在<代码>my_form中不存在,例如:

Phoenix.HTML.Form.input_value(my_form, :non_exist)

例如,我可在“save”handle_event(功能上添加以下代码:

my_form = socket.assigns.my_form
IO.inspect(my_form, label: "[ME]:form")
IO.inspect(Phoenix.HTML.Form.input_value(my_form, :input_int), label: "[ME]: input_value()" )

在我上报时,我在终端窗口看到以下产出:

[ME]:form: %Phoenix.HTML.Form{
  source: %{"input_bool" => true, "input_int" => 3, "input_string" => ""},
  impl: Phoenix.HTML.FormData.Map,
  id: nil,
  name: nil,
  data: %{},
  hidden: [],
  params: %{"input_bool" => true, "input_int" => 3, "input_string" => ""},
  errors: [],
  options: [],
  index: nil,
  action: nil
}
[ME]: input_value(): 3
[ME]updated struct:: %MyApp.MyStruct{some_integer: "3", some_string: "", some_bool: ""}
[debug] Replied in 6ms

But, the value returned was the value which was used to create the form in mount().





相关问题
CSS working only in Firefox

I am trying to create a search text-field like on the Apple website. The HTML looks like this: <div class="frm-search"> <div> <input class="btn" type="image" src="http://www....

image changed but appears the same in browser

I m writing a php script to crop an image. The script overwrites the old image with the new one, but when I reload the page (which is supposed to pickup the new image) I still see the old one. ...

Firefox background image horizontal centering oddity

I am building some basic HTML code for a CMS. One of the page-related options in the CMS is "background image" and "stretch page width / height to background image width / height." so that with large ...

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签