Liftweb - WiringUI and attributes bug using AutoComplete - scala

My problem is happening when I use some attributes in
I have the following error displayed on my webpage:
error on line 146 at column 80: AttValue: " or ' expected
Here is the corresponding line:
try{jQuery("#F114215951950RGX25X").each(function(i) {this.innerHTML = "<span id=\"F114215951957PA3NZS\"></span>";});} catch (e) {}
Here is the code in my snippet:
import net.liftweb.util.ValueCell
import http.SHtml
import net.liftweb.widgets.autocomplete.AutoComplete
object SearchMenu {
/* A valueCell on which WiringUI is used */
val wiringCell= ValueCell(true)
/* The function called in html template */
def display = WiringUI.apply(wiringCell)(displayAjax)
/* The cell to be updated using autocomplete */
val cell = ValueCell("")
/* The function to create and display the autocomplete box */
def displayAjax(value: Boolean)(ns:NodeSeq):NodeSeq = {
def buildQueryName(current: String, limit: Int): Seq[String] = {
if (current.length == 0) Nil
else (1 to limit).map(n => current+""+n).take(limit)
}
AutoComplete("", buildQueryName _, cell.set _)
}
}
Here is the code in my HTML page:
<form class="lift:form.ajax">
<div class="lift:display"> </div>
</form>
Note: the code works if I call displayAjax(true) instead of display, that is to say, if I don't use Wiring.
Note: I think the problem might come from the fact that autocomplete uses a script that is not loaded when using Wiring UI.

It seems like I found 2 bugs in lift for the autocomplete widget. Here is the thread in the official lift mailing list: https://groups.google.com/forum/?fromgroups#!topic/liftweb/Zu5DBqSSW4U

Related

How to select global object inserted dynamically to page with ScalaJS

I tried to insert the Google ReCaptcha script to the page, but I couldn't select the global grecaptcha.
val script = dom.document.createElement("script").asInstanceOf[HTMLScriptElement]
script.setAttribute("src", "https://www.google.com/recaptcha/api.js")
script.setAttribute("async", "true")
script.onload = { (_: Event) =>
println(Dynamic.global.selectDynamic("grecaptcha")) // --> got undefined
}
dom.document.body.appendChild(script)
In the Console window, I can get grecaptcha:
The question is how to select global grecaptcha object?
According to this answer in a vanilla JavaScript environment, you simply have an ordering problem. The steps should be
Append the script to the document
Set the onload event
Set the src attribute
val script = dom.document.createElement("script").asInstanceOf[HTMLScriptElement]
dom.document.body.appendChild(script)
script.onload = { (_: Event) =>
println(Dynamic.global.selectDynamic("grecaptcha"))
}
script.setAttribute("src", "https://www.google.com/recaptcha/api.js")
script.setAttribute("async", "true")

Playframework 2.2.1 Scala - Form bindFromRequest error

I'm trying to register a tuple to a DB and upload the image to Amazon S3.
I divided the code to two parts : 1) Working Code and 2) Non Working Code.
Working code means It works as expected. The image file is uploaded sucessfully to S3.
Non working code is always folding to index_error page which I'm trying to solve but I can't figure out where I'm missing.
Thank you for help!
Working Code
def index = Action {
Ok(views.html.upload_test_index("File Upload In Play"))
}
def uploadFile = Action(parse.multipartFormData) { request =>
request.body.file("fileUpload").map { video =>
val newFile = File.createTempFile("temp-uploaded-", video.filename)
video.ref.moveTo(newFile, true)
new S3Sender(newFile, video.filename).send
}.getOrElse {
Redirect(routes.Application.index)
}
Ok("File has been uploaded")
}
Non Working Code - Controller
val anuncioForm = Form(
tuple(
"label" -> nonEmptyText,
"imgName" -> text
)
)
def createAnuncio = Action(parse.multipartFormData) { implicit request =>
anuncioForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.index_error(formWithErrors)),
{
case (label, imgName) =>
request.body.file("imgName").map { imgName =>
val newFile = File.createTempFile("temp-uploaded-", imgName.filename)
val fileName = imgName.filename
imgName.ref.moveTo(newFile, true)
new S3Sender(newFile, fileName).send
Anuncio.create(label, fileName)
}
println("criou")
Redirect(routes.Application.anuncios)
}
)
}
def anuncios = Action {
Ok(views.html.index(Anuncio.all(), anuncioForm))
}
def newAnuncio = Action {
Ok(views.html.create(anuncioForm))
}
Non Working Code - Template
#(anuncioForm: Form[(String, String)])
#import helper._
#main("Criar um novo anuncio") {
#form(action = routes.Application.createAnuncio, 'enctype -> "multipart/form-data") {
#inputText(anuncioForm("label"))
#*<input type="file" name="imgName">*#
#inputFile(anuncioForm("imgName"))
<input type="submit" value="Create">
}
}
Edited
I used the code below to know the error message.
formWithErrors => BadRequest(views.html.index_error(formWithErrors.errorsAsJson))
Surprisingly I got the message below. I can't figure out why this message?!
{"imgName":["This field is required"]}
Do you need to have the file contents as a part of the form itself? You declare the imgName as a text in the form in your controller, but you use it as a input type="file" in your view, which I would imagine is contradictory.
A few things you could take a look at:
how to handle fileupload into a table in play framework? which talks about separating the file from the form as well as an (untested?) single submit for both a form and a file, and possible some other clues
How to include a picture type in a form in Play!2 in Scala? which is doing something similar to what you are doing
http://www.playframework.com/documentation/2.1.2/ScalaFileUpload

validation of fields in a form in scala with lift frame work

I am working with the Lift framework and Scala. I have a form to sign up to my application, and I want to validate all the fields in it. I have a snippet where I access my form values, and one validation class where I wrote my validation functions. The following code is what I've tried so far. In my Snippet:
if(validationClassObject.validateName(first_name)){
if(validationClassObject.validateName(last_name)){
if(validationClassObject.validateEmail(email)){
if(validationClassObject.validateUserName(name)){
// Adding values to the DB
S.redirectTo("/")
}
else{
S.notice("Invalid User Name")
}
}
else{
S.notice("Invalid Mail Id")
}
}
else{
S.notice("Invalid Last name")
}
}
else{
S.notice("Invalid First Name")
}
In the validationClass I wrote the validation code looks like:
//function for validating mail address
def validateEmail(email: String): Boolean =
"""(\w+)#([\w\.]+)""".r.unapplySeq(email).isDefined
//code for validating remaining fileds like above
This is working, but I know this is not the best way of coding this operation in Scala. How could I modify my code in a more scalable way? How can I use case classes here?
You could do:
def av[T,V](validationFunction: => Boolean, error: => T)(f: => V)={
if(!validationFunction) error
else f
}
def v[V](validationFunction: => Boolean, error: => String)(f: => V)=av(validationFunction,S.notice(error))(f)
import validationCalssObject._
v(validateName(last_name),"Invalid Last name"){v(validateName(name),"Invalid User Name"){...}}
av is a abstract method with T and V as result types for the error function and continue function f. v is the more specific function what expects a string for error and encapsulates the notice() call. we give f as the part in the curly braces v(validation, errormsg){/*todo when there is no problem*/}.
I can't do formatting in comments so I'll post a new answer.
def badName() = if ("name" == "") Some("bad name") else None
def badEmail() = if ("email" == "") Some("bad email") else None
val verifications = List[() => Option[String]](badName, badEmail)
val failed = verifications.flatMap(_())
if (failed.nonEmpty) {
// handle failed
} else {
// your custom logic here
}
if (badName) S.notice
else if (badEmail) S.notice
else if (badDay) S.notice
else { // everything OK...
// return a JsCmd or what else do you wanted here
}
An alternative solution can be written using Option and flatMap, without these all "if"-s hardcoded. If you're interested in that -- ask..

how to get autocomplete text box value using lift web

I am using Lift web framework.
I am implementing an auto-complete text box. When I enter some value in the box a drop-down list opens. If I select a value from that list, only then I am able to access value of text box. If I write a value by myself then I get an empty value.
My code :
var friend_name=""
"#bdayReminder" #> AutoComplete("",
getAllName _,
value => takeAction(value),
List("minChars" -> "3"))
private def takeAction(str: String) {
friend_name = str
}
Please suggest a solution
Disclaimer: I'm the author of following library.
I think lift-combobox could achieve what you want, since it has a feature that let user created the value on-the fly. It use select2 jQuery plugin, so you will have a nice look and feel for the drop-down menu.
For example if you need to get the user-created value, it will simply as the following, note that we usually using Option[T] to denote that the value may not be presented, for example, the user may not selected any item in drop-menu at all:
var friend_name: Option[String] = None
val friendsMenu = new ComboBox(
default = None,
allowCreate = true
) {
// This is where you build your combox suggestion
override def onSearching(term: String): List[ComboItem] = {
val names = List(
ComboItem("f1", "Brian"), ComboItem("f2", "Alice"),
ComboItem("f3", "Luke"), ComboItem("f4", "Smith"),
ComboItem("f5", "Brandon")
)
names.filter(_.text.contains(term))
}
override def onItemSelected(selected: Option[ComboItem]): JsCmd = {
friend_name = selected
// The returned JsCmd will be executed on client side.
Alert("You selected:" + selected)
}
// What you want to do if user added an item that
// does not exist when allowCreate = true.
override def onItemAdded(text: String): JsCmd = {
friend_name = Some(text)
}
}
"#bdayReminder" #> friendsMenu.combobox

Can I use the > operator in a KRL query() selector?

I want to get a nested DIV tag using KRL query() but it complains with
ERROR Rules.pm a8x40 show_xfers Ruleset a8x40 failed: html.query error - Invalid specification ">div" in query: div.recent-transfer>div
Here's the HTML fragment (there are multiple in the file):
<div class='recent-transfer'>
<span>...</span>
<div> <!-- * * * -->
<div>...</div>
<div>...</div>
</div>
</div>
Here's my function:
recent = function() {
t = http:get(the_url).pick("$..content");
t.query("div.recent-transfer>div")
}
I want to select the DIV marked * * *. Do I need to chain several query() statements to get the DIV?
When I tried to reproduce your problem, I didn't get the same error. Instead, I would get a "NOT_FOUND_ERR: DOM Exception 8". In my case, it wasn't a problem with the selector at all; it was the fact that the return value of t.query was an array. If I wanted to use that in, say, a notify(), I had to get the 0th element out of the array and return that instead.
I don't know if that is the same problem you are having. But here's a sample ruleset that works for me:
ruleset a163x61 {
meta {
name "Selector test"
description <<
Testing the query() function
>>
author "Steve Nay"
logging on
}
dispatch {
}
global {
the_url = "http://students.cs.byu.edu/~snay2/content.html";
recent = function() {
t = http:get(the_url).pick("$..content");
// This produces an array.
text = t.query("div.recent-transfer>div");
// We want the text out of the element. Get the first element.
text[0];
// This won't work; throws a "NOT_FOUND_ERR: DOM Exception 8"
//text;
};
}
rule first_rule {
select when pageview ".*" setting ()
pre {
disp = recent();
}
notify("Content:", disp) with sticky=true;
}
}
"div.recent-transfer>div" is a valid query. There was a problem in the KNS causing intermittent failures.
Here's how the function is used, such that the returned array doesn't make problems:
rule add_content {
select when pageview ".*"
foreach recent() setting (item) {
append("div#main", item);
}
}