SHtml.ajaxMultiSelect?

56 views
Skip to first unread message

khxela

unread,
Nov 21, 2013, 6:18:39 PM11/21/13
to lif...@googlegroups.com
I was looking to integrate a lift webapp with chosen.js, and I noticed that there is no SHtml.ajaxMultiSelect (or ajaxMultiSelectObj, etc).  This seems a bit odd to me, since there is are ajaxSelect* and multiSelect*.  Does the functionality exist elsewhere, or is there a reason it hasn't been written?  I looked around and haven't been able to find anything on it, closest thing I saw was this thread https://groups.google.com/forum/#!searchin/liftweb/ajaxmultiselect/liftweb/Rg6bm0KMo8E/ObiwM8lVpmYJ , but the response was geared towards dynamically altering the form vs the lack of ajaxMultiSelect.

Thanks!

Antonio Salazar Cardozo

unread,
Nov 21, 2013, 9:20:10 PM11/21/13
to lif...@googlegroups.com
I'm guessing it simply hasn't been needed until now. Keep in mind ajax*Selects push their results to the server on change. Is that what you're looking for?
Thanks,
Antonio

khxela

unread,
Nov 21, 2013, 9:50:49 PM11/21/13
to lif...@googlegroups.com
Yes.  My use case in this instance is to push the elements to the server on the multi-select's onchange, have the server save a bit of data, then send back a JsCmd interacting with some elements on the page.

Ifedayo Oladapo

unread,
May 10, 2016, 8:13:44 AM5/10/16
to Lift
Building upon Austen Holmes Solution in this stackoverflow post

http://stackoverflow.com/questions/9024279/lift-ajax-multi-select-box
I've come up with this 

def ajaxMultiSelect(opts: Seq[(String, String)], deflt: Seq[String], func: List[String] => JsCmd, attrs: ElemAttr*): Elem =
ajaxMultiSelect_*(opts, deflt, Empty, LFuncHolder(func), attrs: _*)

def ajaxMultiSelect(opts: Seq[(String, String)], deflt: Seq[String], jsFunc: Call, func: List[String] => JsCmd, attrs: ElemAttr*): Elem =
ajaxMultiSelect_*(opts, deflt, Full(jsFunc), LFuncHolder(func), attrs: _*)
//

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(deflt.contains(value))}}</select>)(_ % _)) %
("onchange" -> (jsFunc match {
case Full(f) => {
JsCrVar(key, JsRaw("this")) & deferCall(raw(funcName, key), f)
}
case _ => {
makeAjaxCall(raw(funcName, "this"))
}
}))
}
}

def ajaxUntrustedMultiSelect(opts: Seq[(String, String)], deflt: Seq[String], func: List[String] => JsCmd, attrs: (String, String)*): Elem =
ajaxUntrustedMultiSelect_*(opts, deflt, Empty, LFuncHolder(func), attrs: _* )

def ajaxUntrustedMultiSelect(opts: Seq[(String, String)], deflt: Seq[String], jsFunc: Call, func: List[String] => JsCmd, attrs: (String, String)*): Elem =
ajaxUntrustedMultiSelect_*(opts, deflt, Full(jsFunc), LFuncHolder(func), attrs: _*)

private def ajaxUntrustedMultiSelect_*(opts: Seq[(String, String)], deflt: Seq[String], jsFunc: Box[Call], func: AFuncHolder, attrs: (String, String)*): 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 match {
case Nil => false
case xs => func(xs)
}, func.owner)
fmapFunc(contextFuncBuilder(testFunc)) {
import net.liftweb.http.js.JsCmds.JsCrVar
funcName =>
(attrs.foldLeft(<select multiple="multiple">
{opts.flatMap { case (value, text) => (<option value={value}>
{text}
</option>) % selected(deflt.contains(value))
}}
</select>)(_ % _)) %
("onchange" -> (jsFunc match {
case Full(f) => {
JsCrVar(key, JsRaw("this")) & deferCall(raw(funcName, key), f)
}
case _ => {
makeAjaxCall(raw(funcName, "this"))
}
}))
}
}
Reply all
Reply to author
Forward
0 new messages