Re: [Lift] Re: Ajax button + submitting a form
Hello, the problem is that some form elements are updated, then the function is called, and then the rest of the form elements are updated. My code is more or less something like this: def editElement(elementTemplate: NodeSeq): NodeSeq = { container.elements.flatMap { element: Element = bind(element, elementTemplate, name - { println(bind element name + element.name); SHtml.text(element.name.is, (s: String) = {println(set element name + s); element.name(s); }) } ) } } bind(cont, containerTemplate, name - { println(bind container name + conf.name); SHtml.text(cont.name.is, (s: String) = {println(set container name + s); cont.name(s); }) }, elements - editElement _, addElement - ajaxButton(Text(Add), edit_formid, () = { println(executing function); cont.addElement; reDraw }) ) And the output, when I submit a form where 1 element is already added is: 09:04:23,450 INFO [STDOUT] set container name a 09:04:23,474 INFO [STDOUT] executing function 09:04:23,474 INFO [STDOUT] bind container name a 09:04:23,475 INFO [STDOUT] bind element name 0 09:04:23,476 INFO [STDOUT] bind element name 1 09:04:23,478 INFO [STDOUT] set element name 0a So as you can see first cont.name is set, then the button function is executed, and later the element.names are set. I can try creating a small lift app which would demo this if you'd like. Also, I'm using 1.1-M8. Maybe I should try some newer version? (2.0-SNAPSHOT? 1.1-SNAPSHOT?) Adam On Jan 12, 2010, at 6:03 PM, Marius wrote: I must have misread your post. I did test the ajaxButton above (with your corrections) and the behaviour is correct. Form field functions are invoked first and then your ajax function provided to ajaxButton. Thus this is a good way for adding submit functions for ajax form without the need of using hidden fields and I'll promote this for addition in Shtml (probably with slight modifications). I think the method name should be ajaxSubmit I don't quite get why you're saying this is a problem. What does step 3 needs to accomplish? . all form fields functions are called (except if you have a Shtml.submit because form serialization does not include submits). Then you function is invoked and the response is sent to client. You mentioned that you just need to add multiple buttons for a ajax form ... this version of ajaxButton does just that. Can you please clarify your used case for for for those 3 steps? ... Br's, Marius On Jan 12, 4:20 pm, Adam Warski a...@warski.org wrote: Hello, this *almost* works :). I modified your code a bit and now I have: def ajaxButton(text: NodeSeq, formId: String, func: () = JsCmd, attrs: (String, String)*): Elem = { attrs.foldLeft(fmapFunc(contextFuncBuilder(func))(name = button onclick={makeAjaxCall(JsRaw( LiftRules.jsArtifacts.serialize(formId).toJsCmd + + + Str( + name + =true).toJsCmd)).toJsCmd + ; return false;}{text}/button))(_ % _) } Now the form submits and the right function is executed on the server, and the form is redrawn in the browser. However, the problem is in the ordering of operations. The sequence basically is: (1) update some elements of the form (2) execute the function (3) update the rest of the elements of the form The problem of course is that (2) returns the new content of the form (a SetHtml JsCmd), generated basing on state without all fields updated. I don't quite yet get the rule deciding which fields get updated before calling the function, and which after. One thing I noticed is that if I move the field that is bound first (in bind(...)) to be the last field, it gets moved from group (1) to (3). Also, I thought that maybe the ordering of POST values matters, but swapping Str( + name + =true).toJsCmd and LiftRules.jsArtifacts.serialize(formId).toJsCmd doesn't have any effect. I tried the form many times and always get the same behaviour, so the (1) vs. (3) division seems to be deterministic :) Adam On Jan 11, 2010, at 10:58 PM, Marius wrote: Adam I was thinking of a slightly different approach that does not involve hidden fields: Say you have your current form with SHtml.text, checkboxes or whatever have you: then your ajax buttons (outside the form) like: def ajaxButton(text: NodeSeq, formId: String, func: () = JsCmd, attrs: (String, String)*): Elem = { attrs.foldLeft(fmapFunc(contextFuncBuilder(SFuncHolder(func))) (name = button onclick={makeAjaxCall(JsRaw (LiftRules.jsArtifacts.serialize(formId) + + name.encJs + =_)).toJsCmd + ; return false;}{text}/button))(_ % _) } I haven't tested though but you get the idea ... When we do the ajax call, we serialize the form and add the name parameter as well. This will cause your field functions to be called, and at the end you
Re: [Lift] Re: Ajax button + submitting a form
Hello, Yes please a small app would be best. Please use 2.0-SNAPSHOT. Here it is: http://github.com/adamw/lift-ajax-submit-test/ Steps to reproduce: 1. checkout from git :) 2. run mvn jetty:run 3. go to http://localhost:8080 4. click add once 5. fill in the two fields with some values e.g. container, room 6. click add again 7. the container value will stay, while the room value will disappear. In the logs, you can see: set container name cont executing funtion bind container name cont bind room name bind room name set room name room Also please see this thread: http://groups.google.com/group/liftweb/browse_thread/thread/75750c42ec3a2d7d?hl=en# Yeah, I saw it, as far as I understand the ajaxSubmit is more or less the same as the ajaxButton you did (and I corrected)? Thanks, Adam-- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
Also, interestingly, if you change the order of binding from: bind(cont, containerTemplate, name - { println(bind container name + cont.name); SHtml.text(cont.name, (s: String) = {println(set container name + s); cont.name = s; }) }, rooms - editRoom _, addRoom - ajaxButton(Text(Add), cont_edit, () = { println(executing funtion); cont.rooms += new Room; reDraw }) ) to: bind(cont, containerTemplate, rooms - editRoom _, addRoom - ajaxButton(Text(Add), cont_edit, () = { println(executing funtion); cont.rooms += new Room; reDraw }), name - { println(bind container name + cont.name); SHtml.text(cont.name, (s: String) = {println(set container name + s); cont.name = s; }) } ) then the container name is also lost on submit. The log output is then: executing funtion bind container name bind room name bind room name set container name container set room name room Adam On Jan 13, 2010, at 10:13 AM, Adam Warski wrote: Hello, Yes please a small app would be best. Please use 2.0-SNAPSHOT. Here it is: http://github.com/adamw/lift-ajax-submit-test/ Steps to reproduce: 1. checkout from git :) 2. run mvn jetty:run 3. go to http://localhost:8080 4. click add once 5. fill in the two fields with some values e.g. container, room 6. click add again 7. the container value will stay, while the room value will disappear. In the logs, you can see: set container name cont executing funtion bind container name cont bind room name bind room name set room name room Also please see this thread: http://groups.google.com/group/liftweb/browse_thread/thread/75750c42ec3a2d7d?hl=en# Yeah, I saw it, as far as I understand the ajaxSubmit is more or less the same as the ajaxButton you did (and I corrected)? Thanks, Adam-- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
Hello, this *almost* works :). I modified your code a bit and now I have: def ajaxButton(text: NodeSeq, formId: String, func: () = JsCmd, attrs: (String, String)*): Elem = { attrs.foldLeft(fmapFunc(contextFuncBuilder(func))(name = button onclick={makeAjaxCall(JsRaw( LiftRules.jsArtifacts.serialize(formId).toJsCmd + + + Str( + name + =true).toJsCmd)).toJsCmd + ; return false;}{text}/button))(_ % _) } Now the form submits and the right function is executed on the server, and the form is redrawn in the browser. However, the problem is in the ordering of operations. The sequence basically is: (1) update some elements of the form (2) execute the function (3) update the rest of the elements of the form The problem of course is that (2) returns the new content of the form (a SetHtml JsCmd), generated basing on state without all fields updated. I don't quite yet get the rule deciding which fields get updated before calling the function, and which after. One thing I noticed is that if I move the field that is bound first (in bind(...)) to be the last field, it gets moved from group (1) to (3). Also, I thought that maybe the ordering of POST values matters, but swapping Str( + name + =true).toJsCmd and LiftRules.jsArtifacts.serialize(formId).toJsCmd doesn't have any effect. I tried the form many times and always get the same behaviour, so the (1) vs. (3) division seems to be deterministic :) Adam On Jan 11, 2010, at 10:58 PM, Marius wrote: Adam I was thinking of a slightly different approach that does not involve hidden fields: Say you have your current form with SHtml.text, checkboxes or whatever have you: then your ajax buttons (outside the form) like: def ajaxButton(text: NodeSeq, formId: String, func: () = JsCmd, attrs: (String, String)*): Elem = { attrs.foldLeft(fmapFunc(contextFuncBuilder(SFuncHolder(func))) (name = button onclick={makeAjaxCall(JsRaw (LiftRules.jsArtifacts.serialize(formId) + + name.encJs + =_)).toJsCmd + ; return false;}{text}/button))(_ % _) } I haven't tested though but you get the idea ... When we do the ajax call, we serialize the form and add the name parameter as well. This will cause your field functions to be called, and at the end you ajaxButton function to be called. Inside func function your RequestVar should be preserved due to contextFuncBuilde call. Please let me know if this works. If it does we should probably add it to SHtml. Br's, Marius On Jan 11, 10:54 pm, Adam Warski a...@warski.org wrote: Hello, trying the solution a bit more I came into another problem which I can't solve elegantly. The solution below works nicely for an add button, but a delete button causes more problems: the problem is that with delete, you must know which element should get deleted. In a no-ajax solution, it is enough to do: elements.flatMap { element: Element = bind(element, element Template, name - element.name.toForm, delete - submit(Delete, () = { elements -= element }) ) } which is very nice and easy, as the element to delete gets captured in a closure. But with ajax, and a hidden field used to hold the name of the operation to dispatch, this gets pretty complex: I now need to somehow encode the element to delete (or create a map from some unique identifier to closures which hold the delete methods), so that I can set this as a value of the hidden field. Then in the function passed to SHtml.hidden, I need to decode it back to find the right element. Isn't it a bit of what Lift already does when creating forms? But I still have the feeling that maybe I'm approaching the whole problem from the wrong end, after all, I just want to create an ajax-enabled list of input fields with add and delete operations :) Adam On Jan 11, 1:09 pm, Adam Warski a...@warski.org wrote: Hello, this almost works :). Right now in my form I have a hidden element where the type of the operation to execute will be set: input type=hidden id=operation_id name=operation_id value= / (the name is needed for jquery to set the value, and the id so that I can later read the value using S). I bind the button as following: addElement - button onclick={((JqId(Str(operation_id)) JqAttr(value, Str(add))) SHtml.submitAjaxForm(elements_edit)).toJsCmd+ return false;}{Text(Add element)}/button, and add a hidden field to the whole form to do the processing: bind( ... ) ++ SHtml.hidden(() = { val operationId = S.param(operation_id) operationId.map { opId = opId match { case add = elements += new Element case _ = println(Unknown operation: + opId) } } reDraw }) where elements is a RequestVar object. However for some reason, when I click the button, in the callback I get a new elements RequestVar (so it's
Re: [Lift] Re: Ajax button + submitting a form
Hello, this almost works :). Right now in my form I have a hidden element where the type of the operation to execute will be set: input type=hidden id=operation_id name=operation_id value= / (the name is needed for jquery to set the value, and the id so that I can later read the value using S). I bind the button as following: addElement - button onclick={((JqId(Str(operation_id)) JqAttr(value, Str(add))) SHtml.submitAjaxForm(elements_edit)).toJsCmd+ return false;}{Text(Add element)}/button, and add a hidden field to the whole form to do the processing: bind( ... ) ++ SHtml.hidden(() = { val operationId = S.param(operation_id) operationId.map { opId = opId match { case add = elements += new Element case _ = println(Unknown operation: + opId) } } reDraw }) where elements is a RequestVar object. However for some reason, when I click the button, in the callback I get a new elements RequestVar (so it's initialized to an initial value) and moreover, nothing gets redrawn on the page. What is also quite weird is that the RequestVar is re-initialized, but the snippet instance stays the same. Any ideas? :) I thought that my use-case would be quite common in lift: I just want to add a couple of buttons to my form which execute different actions. Thanks for the help! Adam On Jan 10, 2010, at 6:03 PM, Marius wrote: Sorry I think the syntax would be (I haven't tested it though): button onclick={((JqId(hidden_field_id) JqAttr(value, add)) SHtml.submitAjaxForm(form_ID)).toJsCmd}add/button button onclick={((JqId(hidden_field_id) JqAttr(value, edit)) SHtml.submitAjaxForm(form_ID)).toJsCmd}edit/button button onclick={((JqId(hidden_field_id) JqAttr(value, delete)) SHtml.submitAjaxForm(form_ID)).toJsCmd}delete/button Br's, Marius On Jan 10, 6:58 pm, Marius marius.dan...@gmail.com wrote: On Jan 10, 5:20 pm, Adam Warski a...@warski.org wrote: Hello, ajaxButton(Press me would ya'?, SHtml.submitAjaxForm (form_ID).toJsCmd, (some) = { do your stuff here }) Looking at the source code I think this might work, but I'm having trouble constructing the correct expression to pass to ajaxButton. The method signature requires a Call instance, and SHtml.submitAjaxForm results in a command (JsCmd). Is it possible to somehow combine the two? I was referring to this signature: def ajaxButton(text: NodeSeq, jsExp: JsExp, func: String = JsCmd, attrs: (String, String)*): Elem and not def ajaxButton(text: NodeSeq, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem jsExp will be called before sending the actual ajax. But this may be a bit problematic if your jsExp sends the ajaxForm the ajax request is processed asynchronously at js level meaning the the button ajax request may be send before the actual ajax form processing is done. I'm not sure if this fits your needs Or maybe there is some other, lift-idomatic way to solve my problem? I want to create a form with a list of elements, with three ajax buttons: add, remove and save (adding/removing a row and persisting the list) The first solution I described involving hidden fields will definitely work. I don't think you need to do 2 ajax calls (one for the form and one for the button) but piggy back the button information into a hidden field and only submit the form: Perhaps something like: button onclick={(JqId(hidden_field_id) JqAttr(value, add)) + + SHtml.submitAjaxForm(form_ID).toJsCmd}blah/button By the way, I think there's a small inconsistency; there are 7 overloaded variants for ajaxButton: ajaxButton(text: NodeSeq, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: String, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: NodeSeq, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: String, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: NodeSeq, jsExp: JsExp, func: String = JsCmd, attrs: (String, String)*): Elem and the last one doesn't have a text: String counterpart. Also the javadoc for the last variant is missing information on what's jsExp and what's the argument passed to func. My guess would be that jsExp is evaluated and the result passed to func on the server? Yes jsExp is being evaluated and its result is being sent to server. Please open a defect for this inconsistency. -- Adam -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to
Re: [Lift] Re: Ajax button + submitting a form
Hello, However for some reason, when I click the button, in the callback I get a new elements RequestVar (so it's initialized to an initial value) and moreover, nothing gets redrawn on the page. What is also quite weird is that the RequestVar is re-initialized, but the snippet instance stays the same. Any ideas? :) Yes I think so. You have a regular form with fields like: (SHtml.text. SHtml.hidden etc. right? RequestVars are kept around into a snapshot- restorer only for ajax functions (like for ajaxText etc) and not for regular fields forms. Thus in the Scala function of a SHtml.ajaxText you'll see the RequestVar set when the page was rendered because its state is preserved on purpose by lift. However for regular fields this is not happening. So there is a difference between an ajax-form and ajax fields. Even your form is sent via ajax, the fields are regular fields not ajax fields (... ajax fields do not even need to live inside a form). Therefore for your case the RequestVar's are not preserved and they are renewed when the request comes in. You can keep around that state using a SessionVar. Ah, clear now. And it even works, thanks a lot for the help! :) -- Adam-- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
Hello, I don't think you need a SessionVar. You can just capture the RequestVar's value in a local val and refer to that in the closure. Basically if I understand correctly, this is a typical scenario where you output a form and associate functions with its fields which are to be executed on the *next* request when it's submitted. That request will use a new snippet instance for its output, but first it executes your functions, which have captured references to whatever they refer to. yes, what I'm doing is I capture the value in a function and later in that function I update the request variable with the captured value so that the form is rendered correctly. -- Adam-- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
Hello, trying the solution a bit more I came into another problem which I can't solve elegantly. The solution below works nicely for an add button, but a delete button causes more problems: the problem is that with delete, you must know which element should get deleted. In a no-ajax solution, it is enough to do: elements.flatMap { element: Element = bind(element, element Template, name - element.name.toForm, delete - submit(Delete, () = { elements -= element }) ) } which is very nice and easy, as the element to delete gets captured in a closure. But with ajax, and a hidden field used to hold the name of the operation to dispatch, this gets pretty complex: I now need to somehow encode the element to delete (or create a map from some unique identifier to closures which hold the delete methods), so that I can set this as a value of the hidden field. Then in the function passed to SHtml.hidden, I need to decode it back to find the right element. Isn't it a bit of what Lift already does when creating forms? But I still have the feeling that maybe I'm approaching the whole problem from the wrong end, after all, I just want to create an ajax-enabled list of input fields with add and delete operations :) Adam On Jan 11, 1:09 pm, Adam Warski a...@warski.org wrote: Hello, this almost works :). Right now in my form I have a hidden element where the type of the operation to execute will be set: input type=hidden id=operation_id name=operation_id value= / (the name is needed for jquery to set the value, and the id so that I can later read the value using S). I bind the button as following: addElement - button onclick={((JqId(Str(operation_id)) JqAttr(value, Str(add))) SHtml.submitAjaxForm(elements_edit)).toJsCmd+ return false;}{Text(Add element)}/button, and add a hidden field to the whole form to do the processing: bind( ... ) ++ SHtml.hidden(() = { val operationId = S.param(operation_id) operationId.map { opId = opId match { case add = elements += new Element case _ = println(Unknown operation: + opId) } } reDraw }) where elements is a RequestVar object. However for some reason, when I click the button, in the callback I get a new elements RequestVar (so it's initialized to an initial value) and moreover, nothing gets redrawn on the page. What is also quite weird is that the RequestVar is re-initialized, but the snippet instance stays the same. Any ideas? :) Yes I think so. You have a regular form with fields like: (SHtml.text. SHtml.hidden etc. right? RequestVars are kept around into a snapshot- restorer only for ajax functions (like for ajaxText etc) and not for regular fields forms. Thus in the Scala function of a SHtml.ajaxText you'll see the RequestVar set when the page was rendered because its state is preserved on purpose by lift. However for regular fields this is not happening. So there is a difference between an ajax-form and ajax fields. Even your form is sent via ajax, the fields are regular fields not ajax fields (... ajax fields do not even need to live inside a form). Therefore for your case the RequestVar's are not preserved and they are renewed when the request comes in. You can keep around that state using a SessionVar. I thought that my use-case would be quite common in lift: I just want to add a couple of buttons to my form which execute different actions. Which is very easy to do. But your problem not is how you maintain your specific state (the elements) Thanks for the help! Adam On Jan 10, 2010, at 6:03 PM, Marius wrote: Sorry I think the syntax would be (I haven't tested it though): button onclick={((JqId(hidden_field_id) JqAttr(value, add)) SHtml.submitAjaxForm(form_ID)).toJsCmd}add/button button onclick={((JqId(hidden_field_id) JqAttr(value, edit)) SHtml.submitAjaxForm(form_ID)).toJsCmd}edit/button button onclick={((JqId(hidden_field_id) JqAttr(value, delete)) SHtml.submitAjaxForm(form_ID)).toJsCmd}delete/button Br's, Marius On Jan 10, 6:58 pm, Marius marius.dan...@gmail.com wrote: On Jan 10, 5:20 pm, Adam Warski a...@warski.org wrote: Hello, ajaxButton(Press me would ya'?, SHtml.submitAjaxForm (form_ID).toJsCmd, (some) = { do your stuff here }) Looking at the source code I think this might work, but I'm having trouble constructing the correct expression to pass to ajaxButton. The method signature requires a Call instance, and SHtml.submitAjaxForm results in a command (JsCmd). Is it possible to somehow combine the two? I was referring to this signature: def ajaxButton(text: NodeSeq, jsExp: JsExp, func: String = JsCmd, attrs: (String, String)*): Elem and not def ajaxButton(text: NodeSeq, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem jsExp will be called before sending the actual ajax. But this may be a bit problematic
Re: [Lift] Re: Ajax button + submitting a form
Hello, thanks, but my use-case is a bit different. I want the whole form to be still submitted using a POST (the normal way), and only use ajax for a small fragment of the page (the element editor). So I can't use ajaxForm(...), as this would make all submit buttons use ajax. Adam On Jan 9, 2010, at 3:55 PM, greekscala wrote: Hello, I have a similar use case. For an AjaxForm you have to write: SHtml.ajaxForm( bind(mytags, xml, // binding to your tags ... submit - SHtml.submit(do it, save), ) ++ SHtml.hidden(save) ) You dont need to have a form element in your templates for this to work because ajaxForm will wrap the result of the bind method. For my listelements checkbox, I attach to the checkbox a function, that adds an Id and the checkbox value to a ListBuffer[(Boolean, String)]. (checked and not checked boxes are submittet) Then I filter the List for the selected values a do what I have to do with them. I the above code example, my save method does some db stuff and then returning a JsCmds.SetHtml(an html id, some html/snippet nodeseq) for a redraw. Hope this helps a little with best regards On 9 Jan., 10:48, Adam Warski a...@warski.org wrote: Hello, I have a regular form, which is submitted with a POST (no AJAX here yet). The form contains a list, to which you can add and remove elements using AJAX. So the add and remove buttons are: add - ajaxButton(Add element, () = { elements += new Element; reDraw }) The reDraw method is a SetHtml for the whole form. Now this almost works, with the exception that when I press the add button all other changes in the form are discarded, as the form is not submitted. So, when the button is pressed, I would need to submit the form using ajax and execute a given function on the server. In the archives I found SHtml.submitAjaxForm(formId) method, which I guess does what I need, but I don't know how to combine it with an ajaxButton? -- Thanks, Adam -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
There is also a related problem: how can I have two ajax buttons on one form which submit the form and execute different functions on the server? Using the standard trick: SHtml.ajaxForm(bind(...) ++ SHtml.hidden(submitFunction)) won't work, as I want different functions executed for different buttons. Adam On Jan 10, 2010, at 10:42 AM, Adam Warski wrote: Hello, thanks, but my use-case is a bit different. I want the whole form to be still submitted using a POST (the normal way), and only use ajax for a small fragment of the page (the element editor). So I can't use ajaxForm(...), as this would make all submit buttons use ajax. Adam On Jan 9, 2010, at 3:55 PM, greekscala wrote: Hello, I have a similar use case. For an AjaxForm you have to write: SHtml.ajaxForm( bind(mytags, xml, // binding to your tags ... submit - SHtml.submit(do it, save), ) ++ SHtml.hidden(save) ) You dont need to have a form element in your templates for this to work because ajaxForm will wrap the result of the bind method. For my listelements checkbox, I attach to the checkbox a function, that adds an Id and the checkbox value to a ListBuffer[(Boolean, String)]. (checked and not checked boxes are submittet) Then I filter the List for the selected values a do what I have to do with them. I the above code example, my save method does some db stuff and then returning a JsCmds.SetHtml(an html id, some html/snippet nodeseq) for a redraw. Hope this helps a little with best regards On 9 Jan., 10:48, Adam Warski a...@warski.org wrote: Hello, I have a regular form, which is submitted with a POST (no AJAX here yet). The form contains a list, to which you can add and remove elements using AJAX. So the add and remove buttons are: add - ajaxButton(Add element, () = { elements += new Element; reDraw }) The reDraw method is a SetHtml for the whole form. Now this almost works, with the exception that when I press the add button all other changes in the form are discarded, as the form is not submitted. So, when the button is pressed, I would need to submit the form using ajax and execute a given function on the server. In the archives I found SHtml.submitAjaxForm(formId) method, which I guess does what I need, but I don't know how to combine it with an ajaxButton? -- Thanks, Adam -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
right, I wrote about that in my original post, but how can I execute a button-specific method on the server-side? Thanks, Adam On Jan 10, 2010, at 12:15 PM, Marius wrote: The ajax buttons doesn't have to be inside the form if you use SHtml.submitAjaxForm(form_ID) button onclick={SHtml.submitAjaxForm(form_ID).toJsCmd}blah/button Br's, Marius On Jan 10, 1:08 pm, Adam Warski a...@warski.org wrote: There is also a related problem: how can I have two ajax buttons on one form which submit the form and execute different functions on the server? Using the standard trick: SHtml.ajaxForm(bind(...) ++ SHtml.hidden(submitFunction)) won't work, as I want different functions executed for different buttons. Adam On Jan 10, 2010, at 10:42 AM, Adam Warski wrote: Hello, thanks, but my use-case is a bit different. I want the whole form to be still submitted using a POST (the normal way), and only use ajax for a small fragment of the page (the element editor). So I can't use ajaxForm(...), as this would make all submit buttons use ajax. Adam On Jan 9, 2010, at 3:55 PM, greekscala wrote: Hello, I have a similar use case. For an AjaxForm you have to write: SHtml.ajaxForm( bind(mytags, xml, // binding to your tags ... submit - SHtml.submit(do it, save), ) ++ SHtml.hidden(save) ) You dont need to have a form element in your templates for this to work because ajaxForm will wrap the result of the bind method. For my listelements checkbox, I attach to the checkbox a function, that adds an Id and the checkbox value to a ListBuffer[(Boolean, String)]. (checked and not checked boxes are submittet) Then I filter the List for the selected values a do what I have to do with them. I the above code example, my save method does some db stuff and then returning a JsCmds.SetHtml(an html id, some html/snippet nodeseq) for a redraw. Hope this helps a little with best regards On 9 Jan., 10:48, Adam Warski a...@warski.org wrote: Hello, I have a regular form, which is submitted with a POST (no AJAX here yet). The form contains a list, to which you can add and remove elements using AJAX. So the add and remove buttons are: add - ajaxButton(Add element, () = { elements += new Element; reDraw }) The reDraw method is a SetHtml for the whole form. Now this almost works, with the exception that when I press the add button all other changes in the form are discarded, as the form is not submitted. So, when the button is pressed, I would need to submit the form using ajax and execute a given function on the server. In the archives I found SHtml.submitAjaxForm(formId) method, which I guess does what I need, but I don't know how to combine it with an ajaxButton? -- Thanks, Adam -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Ajax button + submitting a form
Hello, ajaxButton(Press me would ya'?, SHtml.submitAjaxForm (form_ID).toJsCmd, (some) = { do your stuff here }) Looking at the source code I think this might work, but I'm having trouble constructing the correct expression to pass to ajaxButton. The method signature requires a Call instance, and SHtml.submitAjaxForm results in a command (JsCmd). Is it possible to somehow combine the two? Or maybe there is some other, lift-idomatic way to solve my problem? I want to create a form with a list of elements, with three ajax buttons: add, remove and save (adding/removing a row and persisting the list). By the way, I think there's a small inconsistency; there are 7 overloaded variants for ajaxButton: ajaxButton(text: NodeSeq, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: String, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: NodeSeq, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: String, jsFunc: Call, func: () = JsCmd, attrs: (String, String)*): Elem ajaxButton(text: NodeSeq, jsExp: JsExp, func: String = JsCmd, attrs: (String, String)*): Elem and the last one doesn't have a text: String counterpart. Also the javadoc for the last variant is missing information on what's jsExp and what's the argument passed to func. My guess would be that jsExp is evaluated and the result passed to func on the server? -- Adam -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.