Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
lsug-lift.pdf
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Richard Dallaway
March 08, 2010
Programming
32
0
Share
lsug-lift.pdf
London Scala User Group introduction to Lift web development, 8 March 2010.
Richard Dallaway
March 08, 2010
More Decks by Richard Dallaway
See All by Richard Dallaway
AI Roadmap
d6y
0
57
Voice to guide "difficult" recycling queries
d6y
0
76
Brighton Java: Day in the life...
d6y
0
250
Day in the Life of a Functional Programmer
d6y
0
650
Exoplanet Safari
d6y
1
480
Types Working For You
d6y
1
2.7k
Towards Browser and Server Utopia with Scala.js: an example using CRDTs
d6y
0
7.8k
Code Review Gems
d6y
1
2k
Woot for Lift
d6y
2
3.3k
Other Decks in Programming
See All in Programming
空間オーディオの活用
objectiveaudio
0
150
認証統合から始めるフロントエンドの機能単位開発 — マイクロサービス思想の適用
koukimiura
0
100
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
4
450
開発とはなにか、Essenceカーネルで見えるもの
ukin0k0
0
110
Surviving Black Friday: 329 billion requests with Falcon!
ioquatix
0
3k
サプライチェーン攻撃対策「層を重ねて落ちない壁」を10日間で組み上げた話 #TechLeadConf2026
kashewnuts
1
250
Liberating Ruby's Parser from Lexer Hacks
ydah
2
2.7k
Programming with a DJ Controller — not vibe coding
m_seki
3
820
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
370
Spec-Driven Development with AI Agents (Workshop, May 2026)
antonarhipov
3
340
20260514_its_the_context_window_stupid.pdf
heita
0
900
実用!Hono RPC2026
yodaka
2
310
Featured
See All Featured
The Invisible Side of Design
smashingmag
302
52k
Thoughts on Productivity
jonyablonski
76
5.1k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
180
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
190
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Google's AI Overviews - The New Search
badams
0
1k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.7k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
530
Designing for Timeless Needs
cassininazir
0
220
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
230
GraphQLとの向き合い方2022年版
quramy
50
15k
Transcript
Getting started with Lift Richard Dallaway, @d6y
[email protected]
lsug.org
None
Struts Grails Rails PHP JSF Wicket GWT JAX-RS Stripes Spring
MVC Play Seam Seaside Lift Cocoon WebObjects
Struts Grails Rails PHP JSF Wicket GWT JAX-RS Stripes Spring
MVC Play Seam Seaside Lift Cocoon WebObjects Zero Plenty Weirdness
‛ ‛ ‛ ‛ http://liftweb.net
Versions 1.0.3 Updated Jan 2010 2.0 M2 Released Feb 2010
both for Scala 2.7.7
None
None
lift-base/lift-actor lift-base/lift-common lift-base/lift-json lift-base/lift-util lift-base/lift-webkit lift-modules/lift-amqp lift-modules/lift-facebook lift-modules/lift-imaging lift-modules/lift-jta lift-modules/lift-ldap
lift-modules/lift-machine lift-modules/lift-oauth lift-modules/lift-openid lift-modules/lift-osgi lift-modules/lift-paypal lift-modules/lift-testkit lift-modules/lift-textile lift-modules/lift-widgets lift-modules/lift-wizard lift-modules/lift-xmpp lift-persistence/lift-couchdb lift-persistence/lift-jpa lift-persistence/lift-mapper lift-persistence/lift-record $ find . -name lift\* -depth 2 -type d
Agenda • Part I: View first • Part II: Doing
stuff quickly • Part III: Ajax • Part IV: Real time web
The time on this server is: Mon Mar 08 18:40:51
GMT 2010.
<html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello world</h1> <p>The time on this server
is: <lift:Time.now> time appears here </lift:Time.now> </p> </body> </html>
package com.myproject.snippet import scala.xml.NodeSeq class Time { // My <lift:Time.now
/> implementation: def now(xhtml: NodeSeq) = <span>{new java.util.Date()}</span> }
<html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello world</h1> <lift:Time.now> <p>It’s <when:day/> at <when:hour/>.</p>
</lift:Time.now> </body> </html>
package com.myproject.snippet import scala.xml.{NodeSeq,Text} import net.liftweb.util.Helpers._ class Time { def
now(xhtml:NodeSeq) = { val day = "Monday" val hour = "7 o'clock" bind("when", xhtml, "hour" -> <span>{hour}</span>, "day" -> Text(day) ) } }
None
<html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello Canada</h1> <lift:Olympics.results> <table> <table:rows> <tr> <td><r:country>Country
here</r:country></td> <td><r:golds>Gold medal count</r:golds></td> </tr> </table:rows> </table> </lift:Olympics.results> </body> </html>
package com.myprojects.snippet import scala.xml.NodeSeq import net.liftweb.util.Helpers._ class Olympics { case
class Golds(country: String, medals: Int) def results(xhtml: NodeSeq) = { val vancouver = Golds("CAN", 14) :: Golds("GER", 10) :: Golds("GBR", 1) :: Nil // <table:rows> <r:country/> <r:golds/> </table:rows> bind("table", xhtml, ! ! "rows" -> vancouver.flatMap( gold => bind("r", chooseTemplate("table", "rows", xhtml), "country" -> gold.country, "golds" -> gold.medals ) ) ) } }
None
$ mvn archetype:generate \ -DarchetypeCatalog=http://scala-tools.org/ Choose archetype: 1: http://scala-tools.org/ ->
scala-archetype-simple (A simple scala project) 2: http://scala-tools.org/ -> lift-archetype-blank (A blank/empty liftweb project) 3: http://scala-tools.org/ -> lift-archetype-basic (A basic liftweb project (with DB, css, ...)) Choose a number: (1/2/3):
$ mvn archetype:generate \ -DarchetypeGroupId=net.liftweb \ -DarchetypeArtifactId=lift-archetype-blank \ -DarchetypeVersion=2.0-M2 \
-DremoteRepositories=http://scala-tools.org/repo-releases \ -DgroupId=com.example.proj
package com.brightonbloggers.admin.model import net.liftweb.common._ import net.liftweb.util._ import net.liftweb.mapper._ import net.liftweb.http._
class Blog extends LongKeyedMapper[Blog] with IdPK { def getSingleton = Blog object title extends MappedString(this, 20) object url extends MappedString(this, 100) { override def validations = isUrl _ :: super.validations } def isUrl(u:String) = if (url startsWith "http") ! ! ! ! ! ! ! Nil ! ! ! ! ! ! else ! ! ! ! ! ! ! List(FieldError(url, S.?("field.url.error"))) } object Blog extends Blog with LongKeyedMetaMapper[Blog] with CRUDify[Long,Blog] { }
<lift:surround with="default" at="content"> <h1>Ajax blog</h1> <div id="list"> <lift:Blogs.list> <ul> <directory:entry
/> </ul> <directory:new_blog /> </lift:Blogs.list> </div> </lift:surround>
import com.brightonbloggers.admin.model.Blog import scala.xml._ import net.liftweb.common._ import net.liftweb.mapper._ import net.liftweb.http.SHtml._
import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import net.liftweb.http.S._ class Blogs { def list(xhtml: NodeSeq): NodeSeq = { ! def add_new_blog(s: String) = { Blog.create.url(s).title(s).save SetHtml( "list", list(xhtml) ) } bind("directory", xhtml, ! ! "entry" -> Blog.findAll().flatMap( b => <li>{b.url}</li> ), ! ! "new_blog" -> ajaxText("", add_new_blog _) ) } }
package com.brightonbloggers.admin.snippet import com.brightonbloggers.admin.model.Blog import scala.xml._ import net.liftweb.common._ import net.liftweb.mapper._
import net.liftweb.http.SHtml._ import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import net.liftweb.http.S._ class Blogs { def list(xhtml: NodeSeq): NodeSeq = { ! def add_new_blog(s: String) = { Blog.create.url(s).title(s).save SetHtml("list", list(xhtml) ) } def update_blog(blog: Blog)(new_value: String) = { blog.url(new_value).save SetHtml("list", list(xhtml) ) } def click_to_edit(blog: Blog) : NodeSeq = ! ! swappable( <li>{blog.url}</li>, ! ! ! ajaxText(blog.url, update_blog(blog) _ ) ) bind("directory", xhtml, ! ! "entry" -> Blog.findAll().flatMap( click_to_edit _ ), ! ! "new_blog" -> ajaxText("", add_new_blog _) ) } }
None
$MJFOU 4FSWFS 5JNF #SPXTFS6* $0.&5$MJFOU User Activity Client Processing Display
Display Display Comet Event Bus Initialization Data Push Data Push Data Push Display Display Data Push Data Push Server-Side Processing Event Event Event Event Event
def list(xhtml: NodeSeq): NodeSeq = { ! def countable(blog: Blog)
: NodeSeq = ! <li>{link("/static/list", () => { StatsServer ! blog }, Text(blog.url)) }</li> bind("directory", xhtml, ! ! "entry" -> Blog.findAll().flatMap(countable _) )
package com.brightonbloggers.admin.comet import net.liftweb.http._ import net.liftweb.common._ import net.liftweb.util.Helpers._ import net.liftweb.http.js._
import net.liftweb.actor._ import net.liftweb.http.js.JsCmds._ import scala.xml._ object StatsServer extends LiftActor with ListenerManager { var count = 0 override def lowPriority = { case b => count = count + 1 updateListeners() } def createUpdate = count } // <lift:comet type=”StatsWatch” /> class StatsWatch extends CometActor with CometListenee { def registerWith = StatsServer override def render = <div id="total">0</div> override def lowPriority = { case count: Int => partialUpdate(SetHtml("total", Text(count.toString))) } }
Thank you. • Lift book: http://groups.google.com/group/ the-lift-book • Liftweb.net: Wiki,
mailing list, getting started guide • Visit lsug.org, join the meetup.com group
apress discount code LONDONSCALAUQUCUAVGLT
Next Meeting Traits & Mixins Kevin Monday 12 April Here,
Skillsmatter
None