Client to Server ajax

226 views
Skip to first unread message

Alex

unread,
Jul 19, 2012, 5:56:47 AM7/19/12
to lif...@googlegroups.com
I need to implement a sortable list using jquery-ui. The sortable function had the form:

$( ".selector" ).sortable({
update: function(event, ui) { ... }
});

I can call a sortable function from the server side but I need a way to communicate with the server when the 'update' option is fired so I can save an elements position. What is the most lift way to do this?

Jeppe Nejsum Madsen

unread,
Jul 19, 2012, 6:07:22 AM7/19/12
to lif...@googlegroups.com
SHtml.ajaxCall or jsonCall will generate javascript that, when
executed on the client, will call a function on the server.

/Jeppe

Alex

unread,
Jul 20, 2012, 6:44:59 AM7/20/12
to lif...@googlegroups.com
Thanks Jeppe.

I have done the following but got a little confused...

client side javascript:

  function makeSortable(callback) {
    $(function() {
      $(".sortable").sortable();
      $(".sortable").bind("sortupdate", callback);
    });
  }

 function test() {
    return "boba fet";
  }


snippet code:

def sortable = {
    Script(Call("makeSortable", SHtml.ajaxCall("test", println(_))._2))
  }

The client side javascript works fine, I can supply it an alert etc. from the server side and get a response when the "sortupdate" event is fired. However the ajaxCall doesn't appear to be returning anything.

I'm sure I'm making a stupid mistake...

Alex

unread,
Jul 20, 2012, 8:36:43 AM7/20/12
to lif...@googlegroups.com
I changed the Call to:

Call("makeSortable",JsRaw("function() { " + SHtml.ajaxCall("test",println(_))._2.toString + " }") )/

which is now working fine. 

Brent Sowers

unread,
Jul 20, 2012, 2:00:54 PM7/20/12
to lif...@googlegroups.com
What I've done for things like this, where you want to call a lift function from within raw Javascript, is to define a named Javascript function with Function that performs an AJAX call.  So somewhere in the page (what I typically do is create a snippet method that returns this and then just put a <lift:snippet_name.my_javascript_function></lift:snippet_name.my_javascript_function> in the template) return this NodeSeq:

Script(
  Function("sortableUpdateServerCallback", List("paramName"),
    SHtml.ajaxCall(
      JsVar("paramName"), 
      (paramName: String) => // Lift code to do whatever you want and return a JsCmd
    )._2.cmd
  )
)

Then you can write raw Javascript on your page like:

$(".selector").sortable({
  update: function(event, ui) { 
    var callbackValue = "value sent to the server";
    sortableUpdateServerCallback(callbackValue);
  }
});

If you want to send more than one parameter, you can use SHtml.jsonCall, or if you don't need to pass any parameters you can use SHtml.ajaxInvoke.

Brent Sowers
Senior Software Engineer, Audax Health (We're hiring Scala and Lift developers! https://gist.github.com/3025609)

Diego Medina

unread,
Jul 20, 2012, 3:21:06 PM7/20/12
to lif...@googlegroups.com
Thanks for sharing Brent, I added it to the wiki
http://www.assembla.com/spaces/liftweb/wiki/Cool_Tips

Diego
> --
> --
> Lift, the simply functional web framework: http://liftweb.net
> Code: http://github.com/lift
> Discussion: http://groups.google.com/group/liftweb
> Stuck? Help us help you:
> https://www.assembla.com/wiki/show/liftweb/Posting_example_code
>
>
>



--
Diego Medina
Lift/Scala Developer
di...@fmpwizard.com
http://www.fmpwizard.com

Antonio Salazar Cardozo

unread,
Jul 20, 2012, 7:14:46 PM7/20/12
to lif...@googlegroups.com
We take it one step further:

  class CallableFunction(name:String, callback:(String)=>JsCmd, args:List[String] = List()) extends JsCmd {
    override val toJsCmd =
      Function(
        name, args,
        ajaxCall(JsRaw("Array.prototype.slice.call(arguments).join('|')"), callback)._2
      ).toJsCmd
  }

You can then create an arbitrary function:

case class UpdateClosed(callback:(String)=>JsCmd) extends CallableFunction("updateClosed", callback, List("id"))

Above, your Script would then just hold Script(SortableUpdateServerCallback( ... )). Just a tad bit of abstraction.

We typically serve these out in the render segment of a Comet, and they invoke a comet function that sends the CometActor a message to handle the relevant action.

We also have a:

  class AnonCallableFunction(callback:(String)=>JsCmd, args:List[String] = List()) extends JsCmd {
    override val toJsCmd =
      AnonFunc(
        args.mkString(","),
        ajaxCall(JsRaw("Array.prototype.slice.call(arguments).join('|')"), callback)._2
      ).toJsCmd
  }

It's used for when we send down JSON with callbacks.
Thanks,
Antonio

Alex

unread,
Jul 25, 2012, 2:44:52 PM7/25/12
to lif...@googlegroups.com
Thanks Antonio and Brent, very useful examples.

Diego Medina

unread,
Jul 25, 2012, 3:02:09 PM7/25/12
to lif...@googlegroups.com
On Wed, Jul 25, 2012 at 2:44 PM, Alex <alex.m...@gmail.com> wrote:
> Thanks Antonio and Brent, very useful examples.

They were very helpful that I was able to write about them
https://fmpwizard.telegr.am/blog/adding-fields-dynamically-lift

So, thanks for asking the question too :)
Diego
Reply all
Reply to author
Forward
0 new messages