Created
December 5, 2010 16:08
-
-
Save fanf/729195 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.liftweb.http | |
import net.liftweb.common._ | |
/** | |
* That class allow to load and register a snippet for the context of | |
* a Lift request. | |
* | |
* | |
* Such snippet should not be reachable directly from the application, | |
* and so should not be placed in the "snippet" package. | |
* | |
* We could call these local snippets "components". | |
* | |
* This is useful to split a big page into sub part, especially when some of | |
* these part are (complex) forms based on some user action on other part of | |
* the page (and so, forms are contextualized). | |
* | |
* | |
* How to use it: | |
* | |
* <pre> | |
* MyPage.scala | |
* | |
* class MyPage extends DispatchSnippet { | |
* | |
* val myComponentHolder : LocalSnippet[MyComponent] = new LocalSnippet[MyComponent] | |
* | |
* def dispatch = { | |
* case "myComponent" => displayComponent _ | |
* } | |
* | |
* def displayComponent(xml:NodeSeq) : NodeSeq = { | |
* myComponentHolder.is match { | |
* case Failure(m,_,_) => | |
* //error with the component loading or update, display an error message | |
* //here, <lift:MyComponent.renderComponent /> will lead to Lift saying it does not know that class | |
* <span class="error">Error: {m}</span> | |
* case Empty => | |
* //the component was not initialize for that request, show an error message or a way to initialize it (by ajax) | |
* //here too, <lift:MyComponent.renderComponent /> will lead to Lift saying it does not know that class | |
* <span><a href="#" ...>Please click here to init the component</a></span> | |
* case Full(myComponent) => | |
* //render component, as it is now registered | |
* <lift:MyComponent.renderComponent /> | |
* } | |
* } | |
* | |
* //to register the component, you just have to set a value to LocalSnippet | |
* def initComponent : Unit = { | |
* myComponentHolder.set( new MyComponent(context, param, for, that, component) ) | |
* } | |
* } | |
* | |
* MyComponent.scala | |
* | |
* class MyComponent(some:Context, param:For, that:Componenent) extends DispatchSnippet { | |
* | |
* def dispatch = { | |
* case "renderComponent" => renderComponent _ | |
* } | |
* | |
* def renderComponent(xml:NodeSeq) : NodeSeq = { // render component } | |
* } | |
* | |
* </pre> | |
* | |
*/ | |
class LocalSnippet[T <: DispatchSnippet](implicit m: ClassManifest[T]) { | |
private[this] var _snippet : Box[T]= Empty | |
val name = m.erasure.getSimpleName | |
def is = _snippet | |
def set(snippet:Box[T]) : Unit = { | |
_snippet = snippet | |
snippet match { | |
case _:EmptyBox => S.unsetSnippetForClass(name) | |
case Full(s) => S.overrideSnippetForClass(name, s) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That LocalSnippet can be used to build reusable components in Lift.
I'm not sure about the Box, it makes the Snippet use less direct (especially to access to component methods, like initJs(), getComponentState, etc), but it's a good way to force the component user to check if the component is initialized (not Empty) without error (not Failure).