Lift - Autocomplete with Ajax Submission

后端 未结 2 993
难免孤独
难免孤独 2021-02-09 02:32

I would like to use an autocomplete with ajax. So my goal is to have:

  • When the user types something in the text field, some suggestions provided by the server

2条回答
  •  失恋的感觉
    2021-02-09 03:31

    Here's what you need to do.

    1) Make sure you are using Lift 2.5-SNAPSHOT (this is doable in earlier versions, but it's more difficult)

    2) In the snippet you use to render the page, use SHtml.ajaxCall (in particular, you probably want this version: https://github.com/lift/framework/blob/master/web/webkit/src/main/scala/net/liftweb/http/SHtml.scala#L170) which will allow you to register a server side function that accepts your search term and return a JSON response containing the completions. You will also register some action to occur on the JSON response with the JsContext.

    3) The ajaxCall above will return a JsExp object which will result in the ajax request when it's invoked. Embed it within a javascript function on the page using your snippet.

    4) Wire them up with some client side JS.

    Update - Some code to help you out. It can definitely be done more succinctly with Lift 2.5, but due to some inconsistencies in 2.4 I ended up rolling my own ajaxCall like function. S.fmapFunc registers the function on the server side and the function body makes a Lift ajax call from the client, then invokes the res function (which comes from jQuery autocomplete) on the JSON response.

    My jQuery plugin to "activate" the text input

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

    My Scala code that results in the javascript search function:

    
    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');" +
            """
            }
            """)
    

    Update 2 - To add the function above to your page, use a CssSelector transform similar to the one below. The >* means append to anything that already exists within the matched script element. I've got other functions I've defined on that page, and this adds the search function to them.

    
    "script >*" #> autoCompleteJs
    

    You can view source to verify that it exists on the page and can be called just like any other JS function.

提交回复
热议问题