Liftweb:创建一个可以传统和AJAX提交的表单

时间:2011-10-16 14:11:40

标签: ajax scala lift

在Lift Web框架中是否可以创建通过AJAX做出反应的表单(和链接),但是在没有Javascript支持的情况下也可以工作?如果是这样,怎么样?

当我使用<lift:form.ajax>构建表单时,表单的action设置为javascript://,以便在没有JS的情况下不再提交。如果我在没有显式AJAX支持的情况下构建表单,我不知道如何插入AJAX功能。

我想我可以构建一个RESTful接口(无论如何我们必须构建它)并编写自定义Javascript以通过它提交表单。我想避免代码重复:如果可以使用相同的代码处理所有三个输入(RESTful,传统的HTTP POST,AJAX),那将是最好的。

2 个答案:

答案 0 :(得分:4)

查看http://demo.liftweb.net/form_ajax

FormWithAjax.scala

class FormWithAjax extends StatefulSnippet {
   private var firstName = ""
   private var lastName = ""
   private val from = S.referer openOr "/"

def dispatch = {
   case _ => render _
}

def render(xhtml: NodeSeq): NodeSeq =
{
   def validate() {
      (firstName.length, lastName.length) match {
         case (f, n) if f < 2 && n < 2 => S.error("First and last names too short")
         case (f, _) if f < 2 => S.error("First name too short")
         case (_, n) if n < 2 => S.error("Last name too short")
         case _ => S.notice("Thanks!"); S.redirectTo(from)
      }
   }

   bind( "form", xhtml, 
      "first" -> textAjaxTest(firstName, s => firstName = s, s => {S.notice("First name "+s); Noop}),
      "last" -> textAjaxTest(lastName, s => lastName = s, s => {S.notice("Last name "+s); Noop}),
      "submit" -> submit("Send", validate _)
   )
}

form_ajax.html

<lift:surround with="default" at="content">
  Enter your first and last name:<br>
  <form class="lift:FormWithAjax?form=post">
      First Name: <form:first></form:first>
      Last Name: <form:last></form:last>
      <form:submit></form:submit>
   </form>
</lift:surround>

这将在没有javascript的情况下运行:

<form action="/form_ajax" method="post">
   <input name="F1069091373793VHXH01" type="hidden" value="true">
   First Name: <input value="" type="text" name="F1069091373788OVAAWQ" onblur="liftAjax.lift_ajaxHandler('F1069091373789N2AO0C=' + encodeURIComponent(this.value), null, null, null)">
   Last Name: <input value="" type="text" name="F1069091373790VANYVT" onblur="liftAjax.lift_ajaxHandler('F1069091373791CJMQDY=' + encodeURIComponent(this.value), null, null, null)">
   <input name="F1069091383792JGBYWE" type="submit" value="Send">
</form>

答案 1 :(得分:1)

我对Lift没有太多了解,所以我的回答主要集中在替代方法上。 这是基于jQuery的,当Javascript可用时将使用AJAX,如果没有启用Javascript支持,则使用传统的POST。

形式:

<form id="ajaxform" action="formhandler.php" method="post" enctype="multipart/form-data" >

<input name="firstname" type="text" />
<input name="email" type="email" />
<input name="accept" type="submit" value="Send" />

</form>

<div id="result"></div>

JS:

注意:jQuery $.ajax()默认发送为application/x-www-form-urlencoded,也可以设置表单enctype="application/x-www-form-urlencoded"

$("#ajaxform").submit(function(e){

  // Alternative way to prevent default action:
  e.preventDefault();

  $.ajax({
    type: 'POST',
    url: 'formhandler.php',
    // Add method=ajax so in server side we can check if ajax is used instead of traditional post:
    data: $("#ajaxform").serialize()+"&method=ajax",
    success: function(data){ // formhandler.php returned some data:
      // Place returned data <div id="result">here</div>
      $("#result").html(data);
    }
  });

  // Prevent default action (reposting form without ajax):
  return false;
});

服务器端(PHP)

<?php

if (isset($_POST['method']) && $_POST['method'] == 'ajax') {
  // AJAX is used this time, only #result div is updating in this case.
} else {
  // Traditional POST is used to send data, whole page is reloading. Maybe send <html><head>... etc.
}

?>

那么REST呢?

这是你应该决定使用或不使用的东西,它不是支持其他方法(ajax,传统)的替代品,而是更多东西集成在其他方法中。 当然,您始终可以启用或禁用REST功能。 您始终可以将表单method="POST/GET/PUT/DELETE"和ajax调用为RESTful:

...
  $.ajax({
    type: 'PUT',
    url: 'formhandler.php',
...

...
  $.ajax({
    type: 'DELETE',
    url: 'formhandler.php',
...

但是REST要求我们使用XML,JSON,......来处理请求

嗯,浏览器(没有Javascript)不支持,但$.ajax()使用application/x-www-form-urlencoded作为默认编码。

当然,使用Javascript可以始终将数据容器转换为XML或JSON ... 以下是jQuery,JSON对象的完成方式:

/* This is function that converts elements to JSON object,
 * $.fn. is used to add new jQuery plugin serializeObject() */
$.fn.serializeObject = function()
{
   var o = {};
   var a = this.serializeArray();
   $.each(a, function() {
       if (o[this.name]) {
           if (!o[this.name].push) {
               o[this.name] = [o[this.name]];
           }
           o[this.name].push(this.value || '');
       } else {
           o[this.name] = this.value || '';
       }
   });
   return o;
};

但是我想要一个能完成所有事情的AJAX调用:

你是对的,电脑应该做我们的工作。这就是它们的设计目标。

因此,需要做的另一件事是检查我们的原始html表单想要使用的http方法,并使其适应发送 ajax请求,使用相同的方法,无需javascript 支持。 这是之前使用的 JS: 标题下的修改版本:

...
  // Alternative way to prevent default action:
  e.preventDefault();

  // Find out what is method that form wants to use and clone it:
  var restmethod = $('#ajaxform').attr('method');

  // Put form data inside JSON object:
  var data = $('#orderform').serializeObject();
  // Add method=ajax so in server side we can check if ajax is used instead of traditional post:
  data.method = 'ajax';

  $.ajax({
    type: restmethod, // Use method="delete" for ajax if so defined in <form ...>
    url: 'formhandler.php',
    data: data, // data is already serialized as JSON object
...

现在,我们的AJAX处理程序使用在<form method="put" ...>定义的方法(post | get | put | delete)将数据作为JSON对象发送,如果表单方法发生更改,那么我们的ajax处理程序也将适应更改。

这就是全部,一些代码经过测试并且实际上正在使用中,有些代码根本没有经过测试但应该可以正常工作。