afEfanExtra is a library for creating managed libraries of reusable Embedded Fantom (efan) components. Influenced by Java's Tapestry 5, it pairs up Fantom classes and efan templates to encapsulate model / view behaviour.
afEfanExtra is very much in its infancy, with ideas still being fleshed out. It works great in a web / afBedSheet environment, with URLs being automatically mapped to components (coming soon...!), but is presented here context free.
afEfanExtra extends afEfan, is powered by afIoc and works great with afSlim.
Quick Start
Overdue.efan:
Dear <%= userName %>,
It appears the following rented DVDs are overdue:
<%= dvds.join(", ") %>
Please return them at your convenience.
<% app.renderSignOff("The Management") %>
Overdue.fan:
using afIoc
using afEfanExtra
@Component
const mixin Overdue {
// use afIoc services!
@Inject abstract DvdService? dvdService
// template can access mixin fields
abstract Str? userName
// called before the component is rendered
Void initialise(Str userName) {
this.userName = userName
}
// methods may be called from the template
Str[] dvds() {
dvdService.findByName(userName)
}
}
AppModule.fan:
using afIoc
@SubModule { modules=[EfanExtraModule#]}
class AppModule {
static Void bind(ServiceBinder binder) {
binder.bindImpl(DvdService#)
}
@Contribute { serviceType=EfanLibraries# }
static Void contributeEfanLibraries(MappedConfig config) {
// contribute all components in our pod as a library named 'app'
config["app"] = AppModule#.pod
}
}
An efan component consists of a Fantom const mixin class and a corresponding efan template file.
Mixins
Component mixins must be annotated with the @Component facet.
All fields and methods of the mixin are directly accessible in the template. You can even use afIoc's @Inject facet to inject services just as you would in a service class.
Use an initialise() method to pass state into an efan component (the ctx variable is not used). Only one initialise() is allowed. It must be named initialise but may take any number of parameters.
Templates
By default, the template file has the same name as the component (with a .efan extension) and lives anywhere in a pod resource dir. Example component files:
Ensure /fan/components/ is listed in your build.fan as a resDir.
ALIEN-AID: Note resource directories in your build.fan are NOT nested. Adding res/ will NOT add /res/components/ - /res/components/ would need to be added seperately. Example:
resDirs = [`doc/`, `res/`, `res/components/`]
Libraries
Components are managed in libraries. To package up your components, add to the following to your app module:
@Contribute { serviceType=EfanLibraries# }
static Void contributeEfanLibraries(MappedConfig config) {
// contribute all components in the pod as a library named 'app'
config["app"] = AppModule#.pod
}
Library classes are automatically added as fields in your components. Library classes contain component render methods. In the example above, the library (in a field named app) has 2 render methods, available to your templates:
ALIEN-AID: Library render methods are logged at registry startup so you don't have to remember them!
Use with Slim
afEfanExtra works great with afSlim! Add the following to your AppModule and afEfanExtra will automatically pick up component templates with the extenstion .slim:
using afIoc
using afSlim
using afEfanExtra
class AppModule {
static Void bind(ServiceBinder binder) {
binder.bindImpl(Slim#)
}
@Contribute { serviceType=TemplateConverters# }
internal static Void contributeSlimTemplates(MappedConfig config, Slim slim) {
config["slim"] = |File file -> Str| {
slim.parseFromFile(file)
}
}
}
SlimerDude Tue 15 Oct 2013
afEfanExtra v0.0.2 (Preview Release)
afEfanExtra
is a library for creating managed libraries of reusable Embedded Fantom (efan) components. Influenced by Java's Tapestry 5, it pairs up Fantom classes and efan templates to encapsulate model / view behaviour.fanr install -r http://repo.status302.com/fanr/ afEfanExtra
afEfanExtra
is very much in its infancy, with ideas still being fleshed out. It works great in a web / afBedSheet environment, with URLs being automatically mapped to components (coming soon...!), but is presented here context free.afEfanExtra
extends afEfan, is powered by afIoc and works great with afSlim.Quick Start
Overdue.efan:
Overdue.fan:
AppModule.fan:
Then to render a component:
Full example source code available on BitBucket.
Components
An efan component consists of a Fantom
const mixin
class and a corresponding efan template file.Mixins
Component mixins must be annotated with the
@Component
facet.All fields and methods of the mixin are directly accessible in the template. You can even use afIoc's
@Inject
facet to inject services just as you would in a service class.Use an
initialise()
method to pass state into an efan component (thectx
variable is not used). Only oneinitialise()
is allowed. It must be namedinitialise
but may take any number of parameters.Templates
By default, the template file has the same name as the component (with a
.efan
extension) and lives anywhere in a pod resource dir. Example component files:Ensure
/fan/components/
is listed in yourbuild.fan
as a resDir.Libraries
Components are managed in libraries. To package up your components, add to the following to your app module:
Library classes are automatically added as fields in your components. Library classes contain component render methods. In the example above, the library (in a field named
app
) has 2 render methods, available to your templates:Use with Slim
afEfanExtra
works great with afSlim! Add the following to yourAppModule
andafEfanExtra
will automatically pick up component templates with the extenstion.slim
:Have fun!
:)