Nitrogen wf:wire() 不适用于动态内容
Nitrogen wf:wire() does not work for dynamic content
我有 2 个模块:
test2
- 模块创建 div 元素,按钮 ID = wf:temp_id()
- 将 #alert{} 事件连接到它。
- return 这些 HTML 元素,以便它们可以被其他模块使用。
测试
- 模块使用按钮 myBtn 和回发消息创建页面内容 {btn_clicked,myBtn}
- #alert{"myBtn clicked"} 事件,
- 添加空 div,ID 为:id_insert_here - 用作动态元素的占位符
- 调用 test2:get_content("Static"),从模块 test2 添加内容。
然后在事件函数中,它使用#wf:insert_after添加来自test2:get_content("Dynamic").
的内容
预期行为:
- 用户点击 myBtn,
- 出现警告消息"myBtn clicked"
出现新元素"Dynamic content"
这部分正在运行。
用户单击从 test2 生成的 "Static" 部分中的按钮:get_content/1 函数,
- 消息 "Btn_TEMP1" clicked 出现。
到目前为止一切都按预期工作。
现在:
6. 用户单击使用 test2:get_content/1 函数生成的 "Dynamic" 部分中的按钮,并使用 wf:insert_after() 调用添加到页面。
- 预期行为:消息 "btn_TEMP2" 已点击出现。
已实现的行为 - 什么都没发生。
wf:wire 无效。
Q: 如何确保 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.
好问题,需要在氮文档中找到正确答案。
简短的回答是,在 test2:get_content
中,您应该将 wf:wire
替换为 wf:defer
。
它的推理有点长,但它是这样的:
在这两种情况下(静态和动态),当调用 test2:get_content
时,它会按以下顺序执行以下操作:
- 构建一些氮元素并将它们存储在变量中。
- 将动作连接到 (1) 中定义的元素之一
- Return 之前制作的元素。
在静态请求中(或者更确切地说,用氮气的说法,first_request
,因为在氮气中,"static request"指的是纯静态内容,如请求图像文件或其他),这完全没问题。返回静态内容并将其放入页面中,然后将任何有线操作插入模板底部的 [[[script]]]
部分。
但是,在动态 请求中,操作顺序变得很重要。
您定义的 test2:get_content
函数做同样的事情,但是函数被计算并且内容被返回到 wf:insert_after
函数,然后将元素插入到 DOM.
错误隐匿在上面的段落中,但我会融入整体上下文以使其更加明显。使用动态请求:
- 对
wf:insert
_after(或 wf:insert_before
、wf:update
、wf:replace
或其中任何一个)的调用需要 test2:get_content
进行评估第一的。所以评估 test2:get_content()
- 构建一些氮元素并将它们存储在变量中。
- 将动作连接到 (2) 中定义的元素之一
- Return 之前制作的元素。
wf:insert_after
获取那些返回的元素并将它们连接到页面。
这里发生的事情是,因为 wf:insert_after
实际上是最后发生的,所以元素的 wf:wire
无处可去。也就是说,wf:wire
尝试附加的元素在 DOM 中不存在。
就像这样的伪代码:
$('#my_new_element').click(function(){do_something}));
$('#body').insert_bottom("<button id=my_new_element>click</button>");
使用 wf:defer
代替 wf:wire
确保接线发生 在 insert_XXX
函数求值之后。
我有 2 个模块:
test2
- 模块创建 div 元素,按钮 ID = wf:temp_id()
- 将 #alert{} 事件连接到它。
- return 这些 HTML 元素,以便它们可以被其他模块使用。
测试
- 模块使用按钮 myBtn 和回发消息创建页面内容 {btn_clicked,myBtn}
- #alert{"myBtn clicked"} 事件,
- 添加空 div,ID 为:id_insert_here - 用作动态元素的占位符
- 调用 test2:get_content("Static"),从模块 test2 添加内容。
然后在事件函数中,它使用#wf:insert_after添加来自test2:get_content("Dynamic").
的内容预期行为:
- 用户点击 myBtn,
- 出现警告消息"myBtn clicked"
出现新元素"Dynamic content" 这部分正在运行。
用户单击从 test2 生成的 "Static" 部分中的按钮:get_content/1 函数,
- 消息 "Btn_TEMP1" clicked 出现。 到目前为止一切都按预期工作。
现在: 6. 用户单击使用 test2:get_content/1 函数生成的 "Dynamic" 部分中的按钮,并使用 wf:insert_after() 调用添加到页面。
- 预期行为:消息 "btn_TEMP2" 已点击出现。
已实现的行为 - 什么都没发生。
wf:wire 无效。
Q: 如何确保 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.
好问题,需要在氮文档中找到正确答案。
简短的回答是,在 test2:get_content
中,您应该将 wf:wire
替换为 wf:defer
。
它的推理有点长,但它是这样的:
在这两种情况下(静态和动态),当调用 test2:get_content
时,它会按以下顺序执行以下操作:
- 构建一些氮元素并将它们存储在变量中。
- 将动作连接到 (1) 中定义的元素之一
- Return 之前制作的元素。
在静态请求中(或者更确切地说,用氮气的说法,first_request
,因为在氮气中,"static request"指的是纯静态内容,如请求图像文件或其他),这完全没问题。返回静态内容并将其放入页面中,然后将任何有线操作插入模板底部的 [[[script]]]
部分。
但是,在动态 请求中,操作顺序变得很重要。
您定义的 test2:get_content
函数做同样的事情,但是函数被计算并且内容被返回到 wf:insert_after
函数,然后将元素插入到 DOM.
错误隐匿在上面的段落中,但我会融入整体上下文以使其更加明显。使用动态请求:
- 对
wf:insert
_after(或wf:insert_before
、wf:update
、wf:replace
或其中任何一个)的调用需要test2:get_content
进行评估第一的。所以评估test2:get_content()
- 构建一些氮元素并将它们存储在变量中。
- 将动作连接到 (2) 中定义的元素之一
- Return 之前制作的元素。
wf:insert_after
获取那些返回的元素并将它们连接到页面。
这里发生的事情是,因为 wf:insert_after
实际上是最后发生的,所以元素的 wf:wire
无处可去。也就是说,wf:wire
尝试附加的元素在 DOM 中不存在。
就像这样的伪代码:
$('#my_new_element').click(function(){do_something}));
$('#body').insert_bottom("<button id=my_new_element>click</button>");
使用 wf:defer
代替 wf:wire
确保接线发生 在 insert_XXX
函数求值之后。