2012-04-06 13 views
8

私はajaxでオートコンプリートを使いたいと思います。テキストフィールドにユーザーが何かは、サーバが提供するいくつかの提案が表示されたらLift - 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)に(あなたがSHtml.ajaxCallを使用し、ページのレンダリングに使用スニペットでは(これは以前のバージョンでなんとかですが、それはより困難だ)

    2)リフト2.5-SNAPSHOTを使用していることを確認し具体的には、おそらくこのバージョン:https://github.com/lift/framework/blob/master/web/webkit/src/main/scala/net/liftweb/http/SHtml.scala#L170)を使用して、検索語を受け入れ、補完を含むJSON応答を返すサーバー側の関数を登録することができます。また、JsContextを使用してJSON応答で発生するアクションを登録します。

    3)上記のajaxCallは、呼び出されたときにajaxリクエストを返すJsExpオブジェクトを返します。あなたのスニペットを使ってページ上のjavascript関数に埋め込みます。

    4)クライアントサイドJSでワイヤリングします。

    更新 - あなたを助けるためのコード。これはLift 2.5でより簡潔に行うことができますが、2.4ではいくつかの不一致があるため、私は自分のajaxCallのような機能を使い果たしました。 S.fmapFuncは関数をサーバー側に登録し、関数本体はクライアントからLift ajax呼び出しを行い、次にJSON応答のres関数(jQueryオートコンプリートから来る)を呼び出します。に上記機能を追加するには -

    
    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

    私のjQueryプラグインは、テキスト入力javascriptの検索機能になり

    
    (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のコードを "活性化" しますページには、以下のようなCssSelectorトランスフォームを使用します。 > *は、一致するスクリプト要素内に既に存在するものに追加することを意味します。私はそのページで定義した他の関数を持っており、これにより検索関数が追加されます。

    
    "script >*" #> autoCompleteJs 
    

    ソースを表示して、ページに存在することを確認し、他のJS機能と同様に呼び出すことができます。

    +0

    こんにちは、残念ながら私はリフト2.5を使用することはできません。私はリフト2.4M4です。しかし、私がすでに使ったことから、すでに2.4で実装されているコールバックがあるようです。ご回答有難うございます。 –

    +0

    私が今ブロックされている瞬間に自分の質問を更新しましたが、提案は大歓迎です。 –

    +0

    コールバックが機能しないと言ったときに何を意味するのか分かりません。 update_sourceは実行されていますか?もしそうなら、あなたの問題はあなたの利益につながる可能性があります。あなたは非同期呼び出しを行っているので、JSONだけを返すだけでは不十分です。ブラウザはその処理方法を知らないでしょう。アクションを実行するJsCmdを返す必要があります。そのアクションの結果は、JQuery UIオートコンプリートの人口である必要があります。 –

    2

    Dave Whittakerの助けを借りて、ここに私が来た解決策があります。

    私が取得するために、いくつかの動作を変更する必要がありました:

    • 必要なテキスト(オートコンプリートからかどうかを)ajaxText要素に
    • 答えを提出
    • 同じページに複数のオートコンプリートのフォームを持っている可能性をオートコンプリートの提案で何かが選択されたときにぼやけます。ページのヘッダーに挿入する

    Scalaの一部

    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); 
    

    注:私はデイブの答えを受け入れた、鉱山はちょうどのための完全な答えを提供することです私の目的