Reputation: 131
I am new to scala and lift and I want to make a form with some ajax. Therefore main form is from normal stateful snippet and middle content is enclosed with some ajax form(there content in another snippet but not Stateful because I cant use ValueCell in Stateful).
In there I want to add dynamically any no. of multi-select boxes as user want by pressing "ADD" button.
I did it for normal drop-down select by selecting SHtml.ajaxSelect() and save in ValueCell and also save in a session context.
Here I can use ValueCell to store data because ajaxSelect support for ajax. But in multi-select there are not "ajaxMultiSelect"?? So I need to retrieve the data from those dynamically added multi-select boxes to my form variables when pressing submit button in the overall form.
http://seventhings.liftweb.net/wiring - this example is my guide to do my task. Here they use dynamically add text fields. But I want to add multiselect and save data when hitting submit button.
Please help me someone. If u want further clarification I can give.
Thank you ALL...
Upvotes: 10
Views: 1115
Reputation: 1939
I know this is a bit of an older question, but here's my shot (since there still doesn't appear to be an ajax multiSelect in the latest snapshots), and I could see it coming in handy
You can base it off of the regular ajaxSelect. The main changes are:
You have to decide whether you want the callback on change or on blur. In my example, I'll make it onblur, but you could make it configurable.
private def ajaxMultiSelect_*(opts: Seq[(String, String)], deflt: Seq[String], jsFunc: Box[Call], func: AFuncHolder, attrs: ElemAttr*): Elem = {
val optionSelect =
"""function(funcName, element) {
| var postData = ""
| var i = 0;
| var k = 0;
| for (k = 0; k < element.length; k++) {
| if (element[k].selected) {
| if (i == 0)
| postData = funcName + '=' + encodeURIComponent(element[k].value);
| else {
| postData = postData + '&' + funcName + '=' + encodeURIComponent(element[k].value);
| }
| i++;
| }
| }
| return postData;
|}""".stripMargin
val raw = (funcName: String, value: String) => JsRaw(optionSelect + "('" + funcName + "'," + value + ")")
val key = formFuncName
val vals = opts.map(_._1)
val testFunc = LFuncHolder(in => in.filter(v => vals.contains(v)) match {case Nil => false case xs => func(xs)}, func.owner)
fmapFunc((testFunc)) {
funcName =>
(attrs.foldLeft(<select multiple="multiple">{opts.flatMap {case (value, text) => (<option value={value}>{text}</option>) % selected(default.contains(value)))}}</select>)(_ % _)) %
("onblur" -> (jsFunc match {
case Full(f) => JsCrVar(key, JsRaw("this")) & deferCall(raw(funcName, key), f)
case _ => makeAjaxCall(raw(funcName, "this"))
}))
}
}
This should be working, but I didn't test it. If I have time, I'll test it and see if I can get it (and its overloads) added to the master branch.
Good Luck!
-Austen
Upvotes: 0
Reputation: 899
If all you want is multi-selects whose values can be sent to the server when user pushes a "save" button, then a bunch of SHtml.multiselect
objects on an AJAX form should be sufficient.
On the other hand, if you need an AJAX call every time the user changes the value of a multi-select then you probably have to use the same SHtml.multiselect
but add an onchange event handler that calls a JavaScript function containing an ajaxCall.
Here's a bit that creates a JavaScript function doCallback()
and adds it to the page at #placeholder
. This calls commandCallback(commandString)
on the server.
val log = SHtml.ajaxCall(JsRaw("commandString"), commandCallback _)._2.cmd
val f = JsCmds.Function("doCallback", List[String](), log)
("#placeholder" #> JsCmds.Script(f)).apply(ns)
Upvotes: 2