氮wf:wire()不适用于动态内容

时间:2017-03-31 11:35:20

标签: erlang nitrogen

我有2个模块:

test2

  • 模块使用按钮id = wf:temp_id()
  • 创建div元素
  • wire #alert {}事件。
  • 返回这些HTML元素,以便其他模块可以使用它们。

测试

  • 模块使用按钮创建页面内容myBtn和回发消息{btn_clicked,myBtn}
  • #alert {“myBtn clicked”}事件,
  • 添加id为id_insert_here的空div - 用作动态元素的占位符
  • 调用test2:get_content(“Static”),从模块test2添加内容。

然后在事件函数中,它使用#wf:insert_after来添加test2:get_content(“Dynamic”)中的内容。

预期行为:

  1. 用户点击myBtn,
  2. 警告消息“myBtn clicked”出现
  3. 出现了新元素“动态内容” 这部分正在运作。

  4. 用户单击“静态”部分中的按钮,该部分是从test2:get_content / 1函数生成的,

  5. 点击消息“Btn_TEMP1”。 到目前为止,一切都按预期工作。
  6. 现在:  6.用户单击使用test2:get_content / 1函数生成的“Dynamic”部分中的按钮,并使用wf:insert_after()调用添加到页面中。

    1. 预期行为:点击消息“btn_TEMP2”。
    2. 已实现的行为 - 什么都没发生。

      wf:wire无效。

      :如何确保wf:wire()适用于使用wf:insert_XXX函数添加的元素?

      %% -*- mode: nitrogen -*-
      -module (test).
      -compile(export_all).
      -include_lib("../deps/nitrogen_core/include/wf.hrl").
      
      main() -> 
          #template { file="./priv/templates/bare.html",
             bindings=[{'PageTitle',<<"Test">>}]}.
      
      title() -> 
          #template{bindings = L} = main(),
          proplists:get_value('PageTitle',L).
      
      body() ->
          Body = [
             #panel{class="w3-panel w3-green",
                    body = 
                          [#p{text = "some text"},
                           #button {
                              id=myBtn,
                              text="myBtn",
                              postback={btn_clicked,myBtn}
                          },
                          #panel{id = id_insert_here}
                          ]}
           ],
          wf:wire(myBtn, #event{ type= click, actions = [ #alert{text="MyBtn clicked"} ]}),
          Body,
          Content = test2:get_content("Pre-compiled"),
          Body2 = [Body,Content],
          Body2.
      
      event({btn_clicked,myBtn} = Event) ->
          io:format("Event: ~p",[Event]),
          Content = test2:get_content("Dynamic"),
          wf:insert_after(id_insert_here,Content);
      
      event(Event) ->
          io:format(" Unexpected Event: ~p ",[Event]),
          ok.
      %% end of module test
      

      模块测试2:

      -module(test2).
      -compile(export_all).
      -include_lib("../deps/nitrogen_core/include/wf.hrl").
      
      get_content(Title) ->
          MyId = wf:temp_id(),
          BtnText = io_lib:format("Btn_~p",[MyId]),
          Body = [
          #panel{class="w3-panel w3-yellow",
                 body = 
                      [#p{text = Title},
                       #button {
                          id=MyId,
                          text=BtnText
                          }]
              }],
          Msg = io_lib:format("Btn: ~p clicked",[MyId]),
          wf:wire(MyId, #event{ type= click, actions = [ #alert{text= Msg} ]}),
          Body.
      

1 个答案:

答案 0 :(得分:1)

很棒的问题,以及需要在氮气文档中给出正确答案的问题。

简短的回答是,在test2:get_content中,您应该将wf:wire替换为wf:defer

它的推理时间稍长,但它是这样的:

在这两种情况下(静态和动态),当调用test2:get_content时,它会按以下顺序执行以下操作:

  1. 构建一些氮元素并将它们存储在变量中。
  2. 将动作连接到(1)
  3. 中定义的其中一个元素
  4. 返回先前制作的元素。
  5. 静态请求中(或者更确切地说,在氮气用语中,first_request,因为在氮气中,&#34;静态请求&#34;指的是纯静态内容,如请求图像文件或其他),这是完全正常的。返回静态内容,将其放入页面,然后将任何有线操作插入模板底部的[[[script]]]部分。

    但是,在动态请求中,操作顺序变得很重要。

    您定义的test2:get_content函数执行相同的操作,但会评估函数并将内容返回到wf:insert_after函数,然后将函数插入到DOM中。

    错误在上面的段落中巧妙地存在,但我会在整体上下文中使其更加明显。随着动态请求:

    1. wf:insert之后(或wf:insert_before,或wf:updatewf:replace或其中任何一个)的test2:get_content _的调用需要先test2:get_content()进行评估。所以评估wf:insert_after
    2. 构建一些氮元素并将它们存储在变量中。
    3. 将动作连接到(2)
    4. 中定义的元素之一
    5. 返回先前制作的元素。
    6. wf:insert_after获取返回的元素并将它们连接到页面。
    7. 这里发生的事情是因为wf:wire最后有效地发生了,所以元素的wf:wire无处可去。也就是说,元素$('#my_new_element').click(function(){do_something})); $('#body').insert_bottom("<button id=my_new_element>click</button>"); 正在尝试附加到DOM中尚未存在。

      它就像这个伪代码:

      wf:defer

      使用wf:wire代替insert_XXX可确保在 onReceivedError函数评估后发生接线。