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
Getting Started with Lift
Search
Richard Dallaway
March 09, 2010
0
1
Getting Started with Lift
Talk at LSUG 9 March 2010
Richard Dallaway
March 09, 2010
Tweet
Share
More Decks by Richard Dallaway
See All by Richard Dallaway
AI Roadmap
d6y
0
33
Voice to guide "difficult" recycling queries
d6y
0
47
Brighton Java: Day in the life...
d6y
0
180
Day in the Life of a Functional Programmer
d6y
0
560
Exoplanet Safari
d6y
1
380
Types Working For You
d6y
1
2.6k
Towards Browser and Server Utopia with Scala.js: an example using CRDTs
d6y
0
7.5k
Code Review Gems
d6y
1
1.9k
Woot for Lift
d6y
2
3.1k
Featured
See All Featured
Designing for Performance
lara
604
68k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
GitHub's CSS Performance
jonrohan
1030
460k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Writing Fast Ruby
sferik
627
61k
Into the Great Unknown - MozCon
thekraken
32
1.5k
KATA
mclloyd
29
14k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
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-actorlift-base/lift-commonlift-base/lift- jsonlift-base/lift-utillift-base/lift-webkit lift-modules/lift-amqplift-modules/lift-facebooklift- modules/lift-imaginglift-modules/lift-jtalift-modules/ lift-ldaplift-modules/lift-machinelift-modules/lift- oauthlift-modules/lift-openidlift-modules/lift-osgilift- modules/lift-paypallift-modules/lift-testkitlift-modules/ lift-textilelift-modules/lift-widgetslift-modules/lift- wizardlift-modules/lift-xmpp lift-persistence/lift-couchdblift-persistence/lift-
jpalift-persistence/lift-mapperlift-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.
package com.myproject.snippetimport scala.xml.NodeSeqclass Time { // My <lift:Time.now /> implementation:
def now(xhtml: NodeSeq) = <span>{new java.util.Date()}</span> }
package com.myproject.snippetimport 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.snippetimport scala.xml.NodeSeqimport 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.modelimport 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>
package com.brightonbloggers.admin.snippetimport com.brightonbloggers.admin.model.Blogimport 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.snippetimport com.brightonbloggers.admin.model.Blogimport 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
None
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.cometimport 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