我有2个模块:
test2
测试
然后在事件函数中,它使用#wf:insert_after来添加test2:get_content(“Dynamic”)中的内容。
预期行为:
出现了新元素“动态内容” 这部分正在运作。
用户单击“静态”部分中的按钮,该部分是从test2:get_content / 1函数生成的,
现在: 6.用户单击使用test2:get_content / 1函数生成的“Dynamic”部分中的按钮,并使用wf:insert_after()调用添加到页面中。
已实现的行为 - 什么都没发生。
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.
答案 0 :(得分:1)
很棒的问题,以及需要在氮气文档中给出正确答案的问题。
简短的回答是,在test2:get_content
中,您应该将wf:wire
替换为wf:defer
。
它的推理时间稍长,但它是这样的:
在这两种情况下(静态和动态),当调用test2:get_content
时,它会按以下顺序执行以下操作:
在静态请求中(或者更确切地说,在氮气用语中,first_request
,因为在氮气中,&#34;静态请求&#34;指的是纯静态内容,如请求图像文件或其他),这是完全正常的。返回静态内容,将其放入页面,然后将任何有线操作插入模板底部的[[[script]]]
部分。
但是,在动态请求中,操作顺序变得很重要。
您定义的test2:get_content
函数执行相同的操作,但会评估函数并将内容返回到wf:insert_after
函数,然后将函数插入到DOM中。
错误在上面的段落中巧妙地存在,但我会在整体上下文中使其更加明显。随着动态请求:
wf:insert
之后(或wf:insert_before
,或wf:update
或wf:replace
或其中任何一个)的test2:get_content
_的调用需要先test2:get_content()
进行评估。所以评估wf:insert_after
wf:insert_after
获取返回的元素并将它们连接到页面。这里发生的事情是因为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
函数评估后发生接线。