如何在Lift中更改表单的操作

时间:2012-06-08 16:15:59

标签: scala lift

我正在构建一个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的有趣概念。也许我需要沿着这条路走下去,或者可能有一个更好的方法。

3 个答案:

答案 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后显示的发送电子邮件提交按钮,则该代码段会处理发送电子邮件。

不是特别迷人,但它运作得很好。