8

ajaxでオートコンプリートを使用したいと思います。だから私の目標は持っていることです:

  • ユーザーがテキストフィールドに何かを入力すると、サーバーから提供されたいくつかの提案が表示されます(データベースで提案を見つける必要があります)

  • ユーザーが「Enter」を押すか、オートコンプリートボックス以外の場所をクリックするか、提案を選択すると、テキストフィールドの文字列がサーバーに送信されます。

私は最初にliftが提供するオートコンプリートウィジェットを使おうとしましたが、3つの問題に直面しました。

  • これは拡張選択であることが意図されています。つまり、元々は提案された値のみを送信できます。
  • ajaxで使用するためのものではありません。
  • と組み合わせるとバグが発生しWiringUIます。

だから、私の質問は次のとおりです。jqueryオートコンプリートを組み合わせて、リフトでサーバーと対話するにはどうすればよいですか。いくつかのコールバックを使用する必要があると思いますが、それらをマスターしていません。

前もって感謝します。

更新これは私が試した最初の実装ですが、コールバックが機能しません:

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関数を使用してオートコンプリートの提案を更新するには
4

2 に答える 2

8

これがあなたがする必要があることです。

1)Lift 2.5-SNAPSHOTを使用していることを確認します(これは以前のバージョンでは実行可能ですが、より困難です)

2)ページのレンダリングに使用するスニペットで、SHtml.ajaxCallを使用します(特に、このバージョンが必要になる可能性があります:https ://github.com/lift/framework/blob/master/web/webkit/src/main/ scala / net /liftweb / http / SHtml.scala#L170)。これにより、検索語を受け入れるサーバー側関数を登録し、補完を含むJSON応答を返すことができます。また、JSON応答で発生するアクションをJsContextに登録します。

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

4)クライアント側のJSに接続します。

更新-あなたを助けるためのいくつかのコード。それは間違いなくLift2.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);

javascript検索機能をもたらす私のScalaコード:


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関数と同じように呼び出すことができることを確認できます。

于 2012-04-06T16:00:11.760 に答える
2

Dave Whittakerの助けを借りて、これが私が持ってきた解決策です。

以下を取得するには、いくつかの動作を変更する必要がありました。

  • ajaxText要素内の目的のテキスト(オートコンプリートからかどうかに関係なく)
  • 同じページに複数のオートコンプリートフォームがある可能性
  • オートコンプリートの提案で何かが選択されたときにぼかしを入れる前に、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);

注:私はデイブの答えを受け入れました、私の目的のために完全な答えを提供することだけです

于 2012-04-17T08:12:01.957 に答える