Does liftweb have iteration tags? - scala

I was wondering, does Lift have an iteration tag (ex: for, foreach)?
When I was working with JSP, i could easily iterate a List, just with JSP, passing the object to the tag. Something like this, or like this.
I know it's not really the best example, but you do understand my intentions.
To sum up, does this exist with Lift, or if not, how would I manage to do such thing?
The last thing i want to do is hardcode html.

In short: No. Lift’s design strictly separates logic from design and as such forbids the use of generalised tags in the template markup.
Have a look at the view first article in order to see how lift can handle iterations.
An example from the article: Your markup:
<table>
<lift:show.users>
<tr>
<td><f:first_name>David</f:first_name></td>
<td><f:last_name>Pollak</f:last_name></td>
</tr>
</lift:show.users>
</table>
Your code:
class Show {
def users(xhtml: NodeSeq): NodeSeq =
Users.findAll.flatMap(user =>
bind("f", xhtml,
"first_name" -> user.firstName,
"last_name" -> user.nameName
)
)
}
Now, what lift does when it sees the tag <lift:show.users> is calling the corresponding method with the tag’s content as the argument. The tag will then be replaced by the return value of the users method.
The users method does the iteration over all Users and for each user, it binds the values of first and second name to the inner xhtml. All those iterations are then concatenated (through flatMap) and returned.
When I started with lift, I’d always found this approach a little too rigid; having a tiny loop here and there, how could that possibly hurt? But now that I know how easy it is to call and create your own snippets from the template code, I cannot imagine using anything like jsp anymore. It is weak in comparison and clutters your markup. And of course, you lose much of Scala’s power of validation.
Notes:
The reason the template tags are filled with content is for designing purposes. In this case the dummy tags and values are going to be replaced during the bind. The template designers can thus fill the tags with more or less meaningful content which allows the coder to better understand the semantics the designer had in mind.

Related

How do you get around Cloned Templates losing Element References?

I noticed that hyperHTML preserves references I make to elements:
let div = document.createElement("div");
div.textContent = "Before Update";
hyperHTML.bind(document.body)`static1 - ${div} - static2`;
div.textContent = "After Update";
Above will produce a page that says:
static1 - After Update - static2
It is my understanding that hyperHTML ultimately clones an HTML <tempate> element to render the final output. However, don't you typical lose references when cloning an HTML template (like the variable "div" in the example above)?
Therefore, on the initial render, does hyperHTML somehow replace cloned elements with their originals after cloning the HTML template?
Here's how I think it works:
Create an HTML Template of the original template literal while
replacing all interpolations with comments.
Clone the html template with comments left in.
Make elements or document fragments out of each interpolation originally recieved
Replace each comment in the clone with its processed interpolation.
Is this correct?
I am not sure what is the question here, but there is a documentation page, and various examples too to understand how to use hyperHTML, which is not exactly in the way you are using it.
In fact, there's no need to have any reference there because hyperHTML is declarative, so you'd rather write:
function update(text) {
var render = hyperHTML.bind(document.body);
render`static1 - <div>${text}</div> - static2`;
}
and call update("any text") any time you need.
Here's how I think it works ... Is this correct?
No, it's not. hyperHTML doesn't clone anything the way you described, it associates once per unique template tag a sanitized version to the output and finds out all interpolated holes in it.
The part of the library that does this is called domtagger, and the mapping per template literal is based on the standard fact that these are unique per scope:
const templates = [];
function addTemplate(template, value) {
templates.push(template);
return template.join(value);
}
function asTemplate(value) {
return addTemplate`number ${value}!`;
}
asTemplate(1);
asTemplate(2);
asTemplate(Math.random());
templates[0] === templates[1]; // true
templates[1] === templates[2]; // true
// it is always the same template object!
After that, any other element using once that very same tag template will have a clone of that fragment with a map to find holes once and some complex logic to avoid replacing anything that's already known, being that text, attributes, events, or any other kind of node.
hyperHTML never removes comments, it uses these as pin and then uses domdiff to eventually update nodes related to these pins whenever there's a need to update anything.
Domdiff is a vDOM-less implementation of the petit-dom algorithm, which in turns is based on E.W Myers' "An O(ND) Difference Algorithm and Its Variations" paper.
Whenever you have DOM nodes in the holes, hyperHTML understand that and fill these holes with those nodes. If you pass repeatedly the same node, hyperHTML won't do anything 'cause it's full of algorithm and smart decisions, all described in the documentation, to obtain best performance out of its abstraction.
All these things, and much more, normalized for any browser out there, makes hyperHTML weight roughly 7K once minified and gzipped, bit it also offers:
Custom Elements like hooks through onconnected/disconnected listeners
lightweight components through hyperHTML.Component
SVG manipulation as content or via wire
easy Custom Elements definition through HyperHTMLElement class
As summary, if you need these simplifications and you don't want to reinvent the wheel, I suggest you give it a better try.
If you instead are just trying to understand how it works, there's no need to assume anything because the project is fully open source.
So far, all I've read from your questions here and there, is that you just believe to understand how it works so I hope in this reply I've put together all the missing pieces you need to fully understand it.
Do you want to write your own lit/hyperHTML library? Go ahead, feel free to use the domtagger or the domdiff library too, few others are already doing the same.

Creating a reusable component with scalatags

I'd like to create a reusable component with scalatags like this one:
<div class="container">
<button>Delete me</button>
<div class="actual-content">
...
</div>
</div>
and I'd like to register an onclick listener to the button which deletes the whole div container when clicked.
I know that I can do something like this (with jQuery):
div(id:="myid")(
button(onclick:={() => jQuery("#myid").remove()}(Delete me),
div(...)
)
but the problem with this solution is that I'm generating this element automatically and getting the element by id is cumbersome because I'd have to generate unique ids.
Is there a better way? Is there a way to reference a 'myid' div from inside the div?
Thanks
DOM Event callbacks (e.g. what you pass to onClick := ???) receive an instance of an Event as their first parameter. That event has a target property that contains the Node which the event was triggered on (in your case, that would be the button being clicked). That node has a parentNode property which refers to the parent node (element) of the target element. In your case the button's parentNode is your div, the node you want to remove. So you could provide this kind of callback to remove the div:
def clickHandler = (event: Event): Unit = {
val myDiv = event.target.parentNode
myDiv.parentNode.removeChild(myDiv)
}
However, you should know that this style of UI programming is very imperative and does not scale well to a bigger codebases. There are better ways to write frontend apps nowadays. For Scala.js for example there are a few libraries for managing DOM state:
Interfaces to React.js, a popular JS library (SRI or scalajs-react or react4s)
Scalatags-rx
Binding.scala
There are more, these are just the ones that I remember right now.
I don't know of a simple answer for this one, I'm afraid, but here's some food for thought.
Personally, I wound up building a fairly elaborate framework, to deal with this issue among others. That introduces a notion that I wound up calling a GadgetRef, which encapsulates a Scala.Rx Var that references a Scalatags node, outside of the Scalatags tree, and gets set to the actual node when it is created.
So for example, this page defines an Input field in one place, sets it inside the Scalatags tree, and references it in other places.
That's a fairly elaborate framework, though, which isn't yet extracted into a separate library. So it's an idea, but not a silver-bullet answer to the problem...

How to add conditional logic in sightly code for an HTML attribute

I tried searching but somehow i cannot get my way around thinking what do i need to add dynamic tags inside html element using sightly code.
Not sure if this is good practice or not, but wanted to ask.
Now i know how to apply cssclass to class attribute in an href. But what if i want to inject the entire attribute "class='one'" in an href how do i do that?
Can this be done. I know I could do something like
<h3>${properties['jcr:title']}</h3>
but i want to do this,
<div class="col-md-12">
<h3>${properties['jcr:title']}</h3>
Use data-sly-test to determine whether to keep or remove the element, so it's not what you're looking for.
You mentioned that you don't want the class attribute if the variable is null or blank. Your provided code with the ternary operator will do just that.
link
Sightly is very much like JavaScript in the concept of truthy/falsey. In your example if openinnewwindow is truthy (true, not null, or not undefined, etc...), the class attribute will be equal to nonunderline. If openinnewwindow is falsey, the class attribute will not appear in the rendered HTML.
Another way to write this code would be with the logical && operator. This syntax is what you're asking for:
link
See the Sightly specification for more information.

Selecting Multiple Classes in Jquery

I see some posts on this same issue but would like further clarification as I cannot get any of these answer to work especially as I can't pick the answer out of the Jquery documentation.
I want to combine some classes for the convenience of cascading appropriate styling. I could simply replicate the styling in a single class but I am assuming that that would be bad practice.
<div class="left_Item drop_Down" id="col_1">some stuff</div>
$(".left_Item, .drop_Down#col_1").whatever....;
// matches every occurrence of class left_Item with the single occurrence of //drop_Down#col_1 ... this tallies with the multiple selector documentation.
$("#col_1").whatever....;
//obviously does match as the selector is only looking at the id.
//however
$(".drop_Down#col_1").whatever....;
//does not match Does this imply that the classes cannot be matched separately? So....
$(".left_Item.drop_Down#col_1").whatever....;
// various posts on so state that this should match it does not for me. Nor does
$(".left_Item .drop_Down#col_1").whatever....;
$(".left_Item").filter(".drop_Down#col_1).whatever....;
// various posts on so state that this should match also but it does not for me.
So firstly I assume that I am doing the correct thing using multiple classes. If not I'll stop trying to make this work!
Secondly please can some one give the correct jquery syntax to match an element with multiple classes.
Thx
The syntax is as follows (for CSS or jQuery):
.class1.class2
In your case:
$(".left_Item.drop_Down").whatever...
If you want to use an id as well as a class selector, then put the id first:
$("#col_1.left_Item.drop_Down")
Though since ids are supposed to be unique, I don't understand why you don't just use $("#col_1")
If the classes are your main focus then try this.
$('.left_Item.drop_Down').whatever...
But if you want an Id that has classes left_Item drop_Down you might do this
$('#col_1.left_Item.drop_Down').whatever...

What is the purpose of the new "form" attribute on the "object" element in HTML5?

In HTML5, the object element now has a form attribute.
http://dev.w3.org/html5/spec/Overview.html#attr-fae-form
This attribute associates the object element with a form. I'm trying to understand purpose (or result or impact) of this association. I've figured out a couple things:
1) It allows the object element to appear outside of the form element:
http://www.w3.org/TR/html5-diff/#new-attributes
2) It is used to construct the data set:
http://dev.w3.org/html5/spec/Overview.html#categories
Is the object submitted with the rest of the form inputs? Does the server (to whom the form is submitted) now have access to this object (via POST) for processing? What am I missing?
Edit: Still hoping for answers for the 2 questions above regarding form submission...
From the W3 site, it sounds like this solves a pretty big problem with HTML4: "This feature allows authors to work around the lack of support for nested form elements." http://dev.w3.org/html5/spec/Overview.html#form-owner