2012-04-06 35 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); 

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