2012-04-06 36 views
8

我想使用ajax自动完成。所以我的目标是有:电梯 - 使用Ajax提交自动完成

  • 当用户键入的东西在文本字段中,由服务器提供的一些建议出现(我必须找到一个数据库的建议)

  • 当用户按下“输入”,在自动填充框中单击其他位置,或者当他/她选择建议时,文本字段中的字符串将被发送到服务器。

我第一次尝试使用通过电梯提供的自动完成构件,但我面临三个问题:

  • 它意味着是一个扩展的选择,也就是说,你可以原本只提交建议值。
  • 它并不意味着与ajax一起使用。
  • 它与WiringUI结合时会出现错误。

所以,我的问题是:我怎样才能将jquery autocomplete与电梯中的服务器交互。我想我应该使用一些回调,但我不掌握它们。

在此先感谢。

UPDATE这是第一个实现我试过,但回调不工作:

private def update_source(current: String, limit: Int) = { 
    val results = if (current.length == 0) Nil else /* generate list of results */ 
    new JsCmd{def toJsCmd = if(results.nonEmpty) results.mkString("[\"", "\", \"", "\"]") else "[]" } 
} 

def render = { 
    val id = "my-autocomplete" 
    val cb = SHtml.ajaxCall(JsRaw("request"), update_source(_, 4)) 
    val script = Script(new JsCmd{ 
    def toJsCmd = "$(function() {"+ 
     "$(\"#"+id+"\").autocomplete({ "+ 
     "autocomplete: on, "+ 
     "source: function(request, response) {"+ 
     "response("+cb._2.toJsCmd + ");" + 
     "}"+ 
     "})});" 
    }) 

    <head><script charset="utf-8"> {script} </script></head> ++ 
    <span id={id}> {SHtml.ajaxText(init, s=>{ /*set cell to value s*/; Noop}) } </span> 
} 

所以我的想法是:

  • 通过一个SHtml.ajaxText场获得所选择的结果是将被包裹到自动填充字段中
  • 以使用javascript函数更新自动填充建议

回答

8

以下是您需要做的事情。

1)确保您使用的电梯2.5快照(这是在早期版本可行的,但它更困难)

2)在摘要中使用渲染页面,使用SHtml.ajaxCall(以特别是,你可能想要这个版本:https://github.com/lift/framework/blob/master/web/webkit/src/main/scala/net/liftweb/http/SHtml.scala#L170)这将允许你注册一个服务器端函数,接受你的搜索词并返回一个包含完成的JSON响应。您还将在JsContext上注册一些JSON响应的操作。

3)上面的ajaxCall将返回一个JsExp对象,当它被调用时将导致ajax请求。使用您的代码段将其嵌入页面上的JavaScript函数中。

4)将它们与一些客户端JS连接起来。

更新 - 一些代码可以帮助你。使用Lift 2.5可以更简洁地做到这一点,但由于2.4中的一些不一致性,我最终还是滚动了我自己的ajaxCall函数。 S.fmapFunc在服务器端注册函数,函数体从客户端发起Lift ajax调用,然后在JSON响应中调用res函数(来自jQuery自动完成)。

我的jQuery插件 “激活” 的文本输入


(function($) { 
    $.fn.initAssignment = function() { 
    return this.autocomplete({ 
     autoFocus: true, 
     source: function(req, res) { 
       search(req.term, res); 
     }, 
     select: function(event, ui) { 
      assign(ui.item.value, function(data){ 
       eval(data); 
      }); 
      event.preventDefault(); 
      $(this).val(""); 
     }, 
     focus: function(event, ui) { 
      event.preventDefault(); 
     } 
    }); 
    } 
})(jQuery); 

我的Scala代码导致的JavaScript搜索功能:


def autoCompleteJs = JsRaw(""" 
     function search(term, res) { 
     """ + 
      (S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String => 
       val _candidates = 
        if(terms != null && terms.trim() != "") 
        assigneeCandidates(terms) 
        else 
        Nil 
       JsonResponse(JArray(_candidates map { c => c.toJson })) 
      }))) 
      ({ name => 
       "liftAjax.lift_ajaxHandler('" + name 
      })) + 
      "=' + encodeURIComponent(term), " + 
      "function(data){ res(data); }" + 
      ", null, 'json');" + 
     """ 
     } 
     """) 

更新2 - 要添加上面的功能你的页面,使用类似于下面的CssSelector变换。 >表示追加到匹配脚本元素中已存在的任何内容。我在该页面上定义了其他函数,并将搜索功能添加到它们。


"script >*" #> autoCompleteJs 

您可以查看源,以验证它是否存在在页面上可以称得上就像任何其他JS功能。

+0

嗨,不幸的是我不能使用电梯2.5。我在提升2.4 M4。但是,从我已经使用的看来,在2.4中已经实现了回调。感谢您的回答。 – 2012-04-09 10:13:55

+0

我更新了我的问题,我现在被阻挡的时候,任何建议都是值得欢迎的。 – 2012-04-09 10:23:16

+0

当你说回调不起作用时,我不确定你的意思。 update_source是否被执行?如果是这样,你的问题可能与你的回报。您正在进行异步调用,因此只返回JSON是不够的,浏览器不知道如何处理它。您需要返回执行操作的JsCmd,并且该操作的结果应该是JQuery UI自动完成的人口。 – 2012-04-09 15:34:10

2

戴夫·惠特克的帮助下,这里是我想出了解决方案。

我不得不改变一些行为来获得:

  • 所需的文本(从自动完成与否)在ajaxText元素
  • 的可能性有同一个页面上的多个自动完成的表格
  • 提交答案在自动填充建议中选择某些内容时,在模糊之前在ajaxText上。

斯卡拉部分

private def getSugggestions(current: String, limit: Int):List[String] = { 
    /* returns list of suggestions */ 
} 

private def autoCompleteJs = AnonFunc("term, res",JsRaw(
    (S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String => 
    val _candidates = 
     if(terms != null && terms.trim() != "") 
     getSugggestions(terms, 5) 
     else 
     Nil 
    JsonResponse(JArray(_candidates map { c => JString(c)/*.toJson*/ })) 
    }))) 
    ({ name => 
    "liftAjax.lift_ajaxHandler('" + name 
    })) + 
    "=' + encodeURIComponent(term), " + 
    "function(data){ res(data); }" + 
    ", null, 'json');")) 


def xml = { 
    val id = "myId" //possibility to have multiple autocomplete fields on same page 
    Script(OnLoad(JsRaw("jQuery('#"+id+"').createAutocompleteField("+autoCompleteJs.toJsCmd+")")))  ++ 
    SHtml.ajaxText(cell.get, s=>{ cell.set(s); SearchMenu.recomputeResults; Noop}, "id" -> id) 
} 

脚本插入到页面标题:

(function($) { 
    $.fn.createAutocompleteField = function(search) { 
     return this.autocomplete({ 
      autoFocus: true, 
      source: function(req, res) { 
       search(req.term, res); 
      }, 
      select: function(event, ui) { 
       $(this).val(ui.item.value); 
       $(this).blur(); 
      }, 
      focus: function(event, ui) { 
       event.preventDefault(); 
      } 
     }); 
    } 
})(jQuery); 

注:我接受戴夫的回答,我的仅仅是提供一个完整的答案我的目的