How can I set dynamically the parameter of a lift snippet? - scala

Is there a way I can modify dynamically the param of a snippet?
E.g. If I call this URL
host:port/a_page?name=myname
I would like that my page look like this:
<div class="lift:surround?with=default;at=content">
<div class="lift:comet?type=MySnippet;name=myname" >
...
</div>
</div>
Is that even possible? I tried using some javascript in order to extract the param from the url and putting it in the class attribute of the div but in my understanding that won't work becase the scripts will always execute after lift framework does it's magic.
Thanks in advance! Any help is really appreciated.
I used both tips provided to make it work, like ajantis mentioned reading the param directly from snippet is the easiest way but doesnt work in a comet call. Rogach solution works.
So the solution is:
<div class="lift:Ex.wrap">
<div id="myid"></div>
</div>
def wrap = {
val name = "lift:comet?type=MySnippet;name=" + S.param("name").openOr("...")
"#myid" #> <div id="myid" class={name} ></div>
}

Why not just extract http parameter inside snippet processing? i.e.
def render = {
val name = S.param("name").openOr("...")
....
}

You can try wrapping that comet snippet in other snippet, which would transform xml and add that name=myname to class. Like:
<div class="lift:Ex.wrap">
<div class="lift:comet?type=MySnippet"></div>
</div>
class Ex {
def wrap = { (n: NodeSeq) =>
// example transformation
// AntiXML syntax
import com.codecommit.antixml._;
val comet = n \ "div" head;
val comet2 =
comet.copy(attrs = comet.attrs +
("class" -> (comet.attrs("class") + ";name=myname")))
n \ "div" updated (0, comet2) unselect
}
}

Related

How to serialize html form in dart as a string for submission

In jQuery, there is a function to serialize a form element so for example I can submit it as an ajax request.
Let's say we have a form such as this:
<form id="form">
<select name="single">
<option>Single</option>
<option selected="selected">Single2</option>
</select>
<input type="checkbox" name="check" value="check1" id="ch1">
<input name="otherName" value="textValue" type="text">
</form>
If I do this with the help of jquery
var str = $( "form" ).serialize();
console.log(str);
the result would be
single=Single2&check=check1&otherName=textValue
Is there such functionality in dart's FormElement or I have to code it myself? Thanks.
I came up with my own simple solution that might not work in all cases (but for me it is workikng). The procedure is this:
First we need to extract all input or select element names and values from the form into Dart's Map, so the element name will be the key and value the value (e.g. {'single': 'Single2'}).
Then we will loop through this Map and manually create the resulting string.
The code might look something like this:
FormElement form = querySelector('#my-form'); // To select the form
Map data = {};
// Form elements to extract {name: value} from
final formElementSelectors = "select, input";
form.querySelectorAll(formElementSelectors).forEach((SelectElement el) {
data[el.name] = el.value;
});
var parameters = "";
for (var key in data.keys) {
if (parameters.isNotEmpty) {
parameters += "&";
}
parameters += '$key=${data[key]}';
}
Parameters should now contain all the {name: value} pairs from the specified form.
I haven't seen anything like that yet.
In this example Seth Ladd uses Polymers template to assign the form field values to a class which get's serialized.

Why doesn't this pass multiple HTML parameters to template

I know about this and this, but the answers are very strange, and in any case, I am looking to understand why this particular approach does not work:
#myPackage.views.html.ol(
{
Hello
}, {
World
}
)
myPackage.views.html.ol.scala.html
#(ol:Html*)
<ol>
#for(li <- ol) {
<li>
(hi)
<span class="li-body">#li</span>
</li>
}
</ol>
Error:
not found: value Hello
I must lack fundamental understanding about the rules of the template engine, because this seems intuitively correct to me.
The # character marks the beginning of a dynamic statement, so you are no longer in template syntax. It's trying to interpret the arguments to the ol() function as straight Scala/Java code, not the template syntax.
It depends on what exactly you're trying to do, but here are two ways to do it. You could probably also use the #defining helper.
#myPackage.views.html.ol(Html("Hello"), Html("World"))
Another way is to define the Html blocks at the beginning of your view.
#html1 = { Hello }
#html2 = { <strong>World</strong> }
#main(){
#myPackage.views.html.ol(html1, html2)
}
estimatic's answer was correct.
Of what he presented, I would probably have used the #html1 = ... solution, but I found something else, which I hope will benefit some future reader.
HtmlVarArgs.scala
import play.api.templates.Html
import scala.collection.mutable.ListBuffer
class HtmlVarArgs(html: Html) {
private val templates = ListBuffer(html)
def apply(html: Html) = {
templates += html
this
}
def passTo(f: Seq[Html] => Html) = f(templates)
}
object HtmlVarArgs {
def apply(html: Html) = new HtmlVarArgs(html)
}
ol.scala.html
myPackage.views.html.ol.scala.html
#(ol:Html*)
<ol>
#for(li <- ol) {
<li>
(hi)
<span class="li-body">#li</span>
</li>
}
</ol>
And then I can use it in a template as follows:
#HtmlVarArgs {
Hello
} {
World
}.passTo(myPackage.views.html.ol.apply)

How Do I Access A Snippet Option In Lift?

If I have a template like this:
<div class="lift:ThisIsMySnippet?option1=a_value;option2=another_value">
<div class="morestuff">
{embed}
</div>
</div>
and then a snippet like this:
class ThisIsMySnippet {
// I want option1's value!
}
How do I get those values?
I believe you can get the param values of a snippet via the S object like this:
val x = S.attr("option1")
In this case, x will be a Box[String], so if you want to get the value in a safe way you could do this:
val x = S.attr("option1") openOr "defaultValue"

Accessing bind-at values from a snippet in Lift

I have a template that looks like this:
<lift:surround name="default" at="page-content">
<lift:bind-at name="page-title">Home</lift:bind-at>
...
</lift:surround>
The default template looks like this:
<html>
<head>
<title>Title Prefix | </title>
</head>
<body>
<h1><lift:bind name="page-title" /></h1>
<div id="page-content">
<lift:bind name="page-content" />
</div>
</body>
</html>
I want to use a snippet to replace the <title> content with a string that combines "Title Prefix" and the value of <lift:bind-at name="page-title"> (ie: "Home"). I want to contine to use that same value inside the <h1> in the <body>
How can I access a bind-at value from within a snippet that's used in the surrounding template?
I don't believe you can do what you are looking to do with bind-at directives, or at least, I haven't found a way. You should be able to use a snippet to accomplish something similar though.
For example, if you are using SiteMap, the following should be roughly equivalent.
class TitleSnippet {
//Store the value in a requestVar
private var titleVar:String = ""
def first = {
//Retrieve the title for the current Loc as defined in the Sitemap
val locTitle = for (request <- S.request;
loc <- request.location) yield loc.title
//Retrieve the text portion of the tag, and append it to the sitemap title.
//If no sitemap title exists, just display the text
"* *" #> { ns =>
val myTitle = locTitle.map{ t =>
"%s | %s".format(ns.text, t)
} openOr ns.text
titleVar = myTitle
Text(myTitle)
}
}
def title = {
"* *" #> titleVar
}
}
Then, in your template, all you'd have to do is say:
<title data-lift="TitleSnippet.first">Home</title>
So, if we had a page defined like this in the sitemap:
Menu("Sub Page 1") / "subpage"
If everything worked, you should see a title like: <title>Home | Sub Page 1</title> and if you need it elsewhere on the page, all you would have to do is: <h1 data-lift="TitleSnippet.title"></h1>.
If you need access from other snippets, you can also break out titleVar into a companion object and use a RequestVar.

lift snippet: prefix not bound to a namespace

im just starting with lift and scala and have a problem i dont realy understand.
i have the folowing index.html
<html>
<head><title>title</title></head>
<body>
<table>
<lift:Members.list>
<tr>
<td><m:nick/></td>
</tr>
</lift:Members.list>
</table>
</body>
</html>
And the following snippet:
class Members {
def list(xhtml: NodeSeq) =
Member.findAll.flatMap(member => bind("m",xhtml
,"nick" -> member.nickName
))
}
for some reason i get the following error. ive tried alot of things but cant get it to work. whats wrong?
XML Parsing Error: prefix not bound to a namespace
Location: http://localhost:8080/hazardlift-1.0-SNAPSHOT/
Line Number 8, Column 25:<td><m:nick></m:nick></td>
-----------------------------^
Maybe lift doesn't get how to handle your return value. Try forcing an implicit conversion to NodeSeq by specifing it as returntype.
....
def list(xhtml: NodeSeq) : NodeSeq =
....
I just found another cause of this error - an unresolved tag.
I had this HTML:
<div >
<h3>Request Information</h3>
<lift:DetailedRequestData.renderContent>
<f:rowTag></f:rowTag>
</lift:DetailedRequestData.renderContent>
</div>
I had written this for renderContent:
def renderContent(ns: NodeSeq): NodeSeq = {
val key = beginTrans(DisplayData.logger)
var result = ns
try {
var requestID = DisplayData.getParameter("request")
bind("f", ns, "rowTag" -> <p>Request ID: {requestID}</p>)
}
catch {
case t: Throwable => DisplayData.logger.error("[DetailedRequestData$.renderContent] ", t)
}
endTrans(DisplayData.logger, key)
result
}
Since I had not assigned the result of the bind to result, I was returning the unmodified NodeSeq and got the same prefix not bound to a namespace error. Changing the one statement to:
result = bind("f", ns, "rowTag" -> <p>Request ID: {requestID}</p>)
Yes, this was my own stupid fault, but by documenting the problem here, hopefully I will save someone else from having this same problem and not knowing why.