'Elevate your webapps with Scala & Lift', as presented on JEEConf 2012, Kiev, Ukraine
Also see: http://branchandbound.net/blog/conferences/2012/05/jeeconf-tripreport/
Webframeworks
should...
Provide templating
Show dynamic content
Handle user input
Abstract from request/response
cycle?
Be highly interactive?
Preferably: concise, performant, secure
Webframeworks
should...
Provide templating
Lift is view-first
Templates pure HTML5 or XHTML
Embed and surround to compose
default.html with:
<lift:bind name=”content” />
signup.html with:
<lift:surround with=”default”
name=”content”>
<form>
... signup form ...
</form>
<lift:surround />
Webframeworks
should...
Show dynamic content
Pure templates: no code in
templates
Problem?
Webframeworks
should...
Show dynamic content
Pure templates: no code in
templates
Problem?
Webframeworks
should...
Show dynamic content
Snippets transform DOM to DOM
NodeSeq => NodeSeq
Guarantee: well-formedness,
sanitized
Use {request, session, database}
state
Webframeworks
should...
Show dynamic content
Snippet View
class IndexSnippet { .. surrounding html ..
def date(in: NodeSeq): NodeSeq = <lift:indexSnippet.date>
Helpers.bind("b", in, <div>Current date:
"date" -> new Date()) <b:date>
10:00:00 1/1/2012
} </b:date>
</div>
</lift:indexSnippet.date>
Webframeworks
should...
Show dynamic content
‘Operators’ and implicit conversions:
“date”.->(new Date())
results in a tuple:
(“date”, new Date())
Snippet View
class IndexSnippet { .. surrounding html ..
def date(in: NodeSeq): NodeSeq = <lift:indexSnippet.date>
Helpers.bind("b", in, <div>Current date:
"date" -> new Date()) <b:date>
10:00:00 1/1/2012
} </b:date>
</div>
</lift:indexSnippet.date>
Webframeworks
should...
Show dynamic content
Snippet (CSS binding) View
class CssSnippet { .. surrounding html ..
<div class="lift:cssSnippet.date">
def date: NodeSeq => NodeSeq = Current date:
"#date" #> currentDate <span id="date">10:00:00
1/1/2012</span>
} </div>
.. surrounding html ..
Webframeworks
should...
Show dynamic content
Constructs a function
NodeSeq => NodeSeq
Snippet (CSS binding) View
class CssSnippet { .. surrounding html ..
<div class="lift:cssSnippet.date">
def date: NodeSeq => NodeSeq = Current date:
"#date" #> currentDate <span id="date">10:00:00
1/1/2012</span>
} </div>
.. surrounding html ..
Webframeworks
should...
Show dynamic content
Implicit conversion from
String to ToCssBindPromoter
Snippet (CSS binding) View
class CssSnippet { .. surrounding html ..
<div class="lift:cssSnippet.date">
def date: NodeSeq => NodeSeq = Current date:
"#date" #> currentDate <span id="date">10:00:00
1/1/2012</span>
} </div>
.. surrounding html ..
Webframeworks
should...
Show dynamic content
With HTML5 may also be
data-lift=”cssSnippet.date”
Snippet (CSS binding) View
class CssSnippet { .. surrounding html ..
<div class="lift:cssSnippet.date">
def date: NodeSeq => NodeSeq = Current date:
"#date" #> currentDate <span id="date">10:00:00
1/1/2012</span>
} </div>
.. surrounding html ..
Webframeworks
should...
Show dynamic content
No MVC: MenuSnippet
View <=> Snippet
NewsSnippet
Many <=> Many
FormSnippet
Webframeworks
should...
Handle user input
Add server-side behavior to DOM
... with snippets
Behavior captured in closures
... managed by Lift, executed after
submit
Plain and Ajax requests unified
Primarily
stateful!
Webframeworks
should...
Handle user input
Snippet View
class FormSnippet {
def nameForm = { .. surrounding html ..
var name = "" <form method="POST"
def processForm() = class="lift:FormSnippet.nameForm">
println(name) <input id="nameField"
type="text"/>
"#nameField" #> <input id="submitButton"
type="submit"/>
SHtml.text(name, name = _) </form>
&
"#submitButton" #> .. surrounding html ..
SHtml.submit("Click",
processForm)
}
}
Webframeworks
should...
Handle user input
Method within method:
Snippet View
references name in outer scope
class FormSnippet {
def nameForm = { .. surrounding html ..
var name = "" <form method="POST"
def processForm() = class="lift:FormSnippet.nameForm">
println(name) <input id="nameField"
type="text"/>
"#nameField" #> <input id="submitButton"
type="submit"/>
SHtml.text(name, name = _) </form>
&
"#submitButton" #> .. surrounding html ..
SHtml.submit("Click",
processForm)
}
}
Webframeworks
should...
Handle user input
Equivalent to:
(inputName: String) => name = inputName
Snippet View
Closure in shorthand format
class FormSnippet {
def nameForm = { .. surrounding html ..
var name = "" <form method="POST"
def processForm() = class="lift:FormSnippet.nameForm">
println(name) <input id="nameField"
type="text"/>
"#nameField" #> <input id="submitButton"
type="submit"/>
SHtml.text(name, name = _) </form>
&
"#submitButton" #> .. surrounding html ..
SHtml.submit("Click",
processForm)
}
}
Webframeworks
should...
Handle user input
Combine 2 CSS transforms
into single aggregated transformation
Snippet View
def &(other: CssSel): CssSel
class FormSnippet {
def nameForm = { .. surrounding html ..
var name = "" <form method="POST"
def processForm() = class="lift:FormSnippet.nameForm">
println(name) <input id="nameField"
type="text"/>
"#nameField" #> <input id="submitButton"
type="submit"/>
SHtml.text(name, name = _) </form>
&
"#submitButton" #> .. surrounding html ..
SHtml.submit("Click",
processForm)
}
}
Webframeworks
should...
Handle user input
SHtml components: powerful but low-
level
abstractions:
LiftScreen Wizard
Declarative Multipage wizards
forms Backbutton
Validation support
Strongly typed ‘Conversations’
Comet
... with actors!
Asynchronous
Mailbox serializes processing
Lightweight
Event-driven execution Local state
Behavior
mailbox
Comet
... with actors!
Asynchronous
Mailbox serializes processing
Lightweight
Event-driven execution Local state
Send message to actor: Behavior
actor ! MyMessage(“payload”)
mailbox
Wrapping up
Designer friendly, logic free views
Concise; leverages Scala
Comet/Ajax integration second to none
Mature framework with great community
Relatively steep learning curve
Documentation slowly improving
Stateful, but no session replication
Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
\n
\n
Show NameSnippet, introduce S object (with notices), stateful part\n
Show NameSnippet, introduce S object (with notices), stateful part\n
Show NameSnippet, introduce S object (with notices), stateful part\n
Show NameSnippet, introduce S object (with notices), stateful part\n
Show NameSnippet, introduce S object (with notices), stateful part\n
Show NameSnippet, introduce S object (with notices), stateful part\n
First show Ajax autocomplete\n
\n
you can have millions of actors per JVM\n
you can have millions of actors per JVM\n
\n
\n
\n
Documentation, err msg/dev experience: Play better\nView-first vs MVC with code in templates + Servlet based vs. custom HTTP stack\nLift: security, more freedom (more rope to hang yourself), Play more handholding\nLift doesn&#x2019;t give one true way\n