我正在构建一个Lift应用程序,其中一个页面基于Lift演示中的“文件上传”示例:http://demo.liftweb.net/file_upload。
如果您查看source code for that page ...您会看到有一个Lift“代码段”标记,周围有两个“选择”标记:
<lift:snippet type="misc:upload" form="post" multipart="true">
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
</choose:post>
<choose:get>
Select a file to upload: <ul:file_upload></ul:file_upload><br >
<input type="submit" value="Upload File">
</choose:get>
</lift:snippet>
这个想法是当用户第一次点击页面(即GET请求)时,Lift会显示上传文件的表单。当用户提交表单(即POST请求到同一页面)时,Lift会显示正在处理的文件的结果。
在我的应用程序中,新的皱纹是我的“结果”POST视图需要还包含一个表单。我想提供一个文本输入供用户输入一个电子邮件地址,一个提交按钮,按下后将发送有关已处理文件的信息:
...
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!-- BEGIN NEW STUFF -->
Output: <br/>
<textarea rows="30" cols="100"><ul:output></ul:output></textarea>
<br/><br/>
Email the above output to this email address:<br/>
<ul:email/><br/>
<input type="submit" value="Email"/>
<!-- END NEW STUFF -->
</choose:post>
...
但是,此页面的GET和POST版本都由同一个Lift生成的表单包装,在两种情况下都将其“action”设置为相同的片段。如何更改此选项,以便在POST版本中,表单的操作更改为不同的代码段?
在一个典型的Web框架中,我会通过“onclick”事件和两个基本的JavaScript行来处理这样的事情。但是,我还没有开始关注Lift的问题...错误,有关在Scala中编写JavaScript的有趣概念。也许我需要沿着这条路走下去,或者可能有一个更好的方法。
答案 0 :(得分:2)
首先,我建议您使用Lift的新设计师友好的CSS绑定,而不是自定义的XHTML标记。
当你使用Lift的片段时,你应该记住的一件事是,它是递归的,你可以将一个电梯片段放在另一个片段的HTML块中。
例如,如果您希望POST后有另一个表单,那么只需将其放入块中即可。
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!--
The following is same as <lift:snippet type="EMailForm" form="post" multipart="true">
-->
<form action="" method="post" data-lift="EMailForm">
<input type="text" name="email"/>
<input type="submit" />
</form>
</choose:post>
然后处理片段类EMailForm的电子邮件表单操作。
最后,您可以使用隐藏表单元素或SessionVar传递文件名/ minetype和其他信息。
答案 1 :(得分:1)
我同意Brian,使用Lift的新设计师友好的CSS绑定。
使用两个单独的表单,一个用于文件上传,另一个用于提交电子邮件。当第一个表单处理完毕后,使用S.seeOther将用户重定向到第二个表单。
我也更喜欢新的'数据提升'HTML属性。
文件上传HTML:
<div data-lift="uploadSnippet?form=post">
<input type="file" id="filename" />
<input type="submit" id="submit" />
</div
文件上传代码段:
class uploadSnippet {
def processUpload = {
// do your processing
....
if (success)
S.seeOther("/getemail")
// if processing fails, just allow this method to exit to re-render your
// file upload form
}
def render = {
"#filename" #> SHtml.fileUpload(...) &
"#submit" #> SHtml.submit("Upload", processUpload _ )
}
}
GetEmail HTML:
<div data-lift="getEmailSnippet?form=post">
<input type="text" id="email" />
<input type="submit" id="submit" />
</div
获取电子邮件摘要:
class getEmailSnippet {
def processSubmit = {
....
}
def render = {
"#email" #> SHtml.text(...) &
"#submit" #> SHtml.submit("Upload", processSubmit _ )
}
我的博客文章中有关于使用RequestVar的表单处理的更多信息: http://tech.damianhelme.com/understanding-lifts-requestvars
如果您想了解更多细节,请与我们联系。
希望这很有用
干杯
达米安
答案 2 :(得分:0)
如果有人在接下来的几天内提出更优雅(或“升降式”)的方法,那么我会接受他们的回答。但是,我自己想出了一种解决方法。
我保留了当前的布局,其中视图有一个GET块和一个POST块都提交到相同的片段功能。代码段功能仍然有if-else
块,根据是GET还是POST来处理每个请求。
但是,现在我在POST块的中还有一个辅助if-else
块。内部if-else
查看单击的提交按钮的名称。如果提交按钮是用于上载文件的按钮,则该代码段处理文件的上载和处理。否则,如果是第一次POST后显示的发送电子邮件提交按钮,则该代码段会处理发送电子邮件。
不是特别迷人,但它运作得很好。