[Lift] Record-aware secondary menu?

2009-05-09 Thread Clemens Oertel

Hi,

In addition to the usual primary menu (Home, List entries, Add entry,  
Log in/out, ...), I would like to introduce a secondary, record-aware  
menu to my site. The entries in this menu would contain, for example,  
"Edit current record", "Delete current record", "Show current  
record", ...
There are multiple types of records (which all have their own separate  
edit/delete/show/... snippet), and all of those link targets have a  
corresponding (currently hidden) entry in the sitemap.
So I thought it'd be nice if I could reuse the sitemap for this, by  
creating a separate Loc group for all the secondary menu entries for a  
given record type.

I am currently using SHtml.link and RequestVar's to handle links, e.g.

object requestedResource extends RequestVar[Box[T]](Empty)
object requestedReturnTarget extends RequestVar[Box[URL]](Empty)

SHtml.link("/edit", () => { requestedResource(Full(theRecord));  
requestedReturnTarget(Full(returnTarget))) }, "Edit")

Now I am wondering what's the best way to merge the functionality of  
the menu with SHtml.link.
How can I get a menu entry to use the current values of some  
RequestVars to generate its link, such as a "edit current record" menu  
entry?

Or would I have to bring the record-ID into the Loc in order to  
achieve something like this, such as
Menu(Loc("EditRecord", List("record",  
RecordOps.currentRecord.is.id.toString, "edit"), "Edit"))
and then use some pattern matching during dispatching to retrieve the  
record ID again?

Thank you,
Clemens

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Is Lift the right tool for us?

2009-04-21 Thread Clemens Oertel

> If your project is more than a simple app (as I'm certain it is), I
> would go with JPA. Record is not ready yet, and Mapper is pretty
> limited. For example, AFAIK Mapper doesn't do many-to-many  
> associations.
> I've had a lot of success with JPA/Hibernate, and it's getting pretty
> solid in Lift now -- there are even Maven archetypes for it.
>
>  I've yet to dig into Mapper/Record. What are the main benefits of  
> these (besides the obvious simplicity you get when not needing to  
> use JPA)?
>

Here's my experience: I started out with mapper for my current  
project, and ended up overriding/rewriting most of the functionality,  
to make it work for my (maybe unusual) requirements. I have pretty  
much duplicated the entire mapper class/trait hierarchy, bit by bit.  
For example, Mapper does not like dealing with null values for types  
that are not nullable in Scala. Mapper has, for example, 0 hard-coded  
as default value for int's for which no value is given. No  
insurmountable obstacles, but things might take more work than one  
thinks initially. There's just no free lunch.

Since mapper combines so many aspects, it might take a considerable  
amount of effort to isolate concerns when switching from mapper to JPA  
or similar.

I will be switching to JPA in the next two weeks.

Best,
Clemens


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: (created|updated|deleted)_(by|at) trait

2009-04-10 Thread Clemens Oertel

Hi Franz,

Here's what I did, roughly:

trait TimeStamped[OwnerType <: ExtMapper[OwnerType]] {
   this: ExtMapper[OwnerType] =>

   private val thisTyped = this.asInstanceOf[MapperType]

   object createdOn extends ExtMappedDateTime(thisTyped) with  
LifecycleCallbacks {
 override def beforeCreate = this(new Date)
   }

   object updatedOn extends ExtMappedDateTime(thisTyped) with  
LifecycleCallbacks {
 override def beforeUpdate = this(new Date)
   }
}

trait ExtMapper[OwnerType <: ExtMapper[OwnerType]] extends  
Mapper[OwnerType]
 with TimeStamped[OwnerType] with UserStamped[OwnerType]
{
   self: OwnerType =>

   // A lot more stuff here ...
}

Best,
Clemens


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Rails -> Lift

2009-04-09 Thread Clemens Oertel
> On Thu, Apr 9, 2009 at 9:42 AM, Clemens Oertel  > wrote:
>
> I don't think it's necessary to make a final decision about your IDE
> at any time. AFAIK, all major IDEs work quite well with Maven's pom
> files, so it's very easy to switch IDEs at any time.
>
> WOAAAH  I beg to differ.   Actually some IDEs work much better  
> with Maven pom's than others.  It depends on how you like to arrange  
> your projects and work on them.  (At work, the IntelliJ users get a  
> much different feel for multi-module projects than Eclipse users).

Fair enough. Let me rephrase. With the IDEs that I have tried, and  
only for the versions of said IDEs that I have used, and only for the  
Scala/Lift projects that I worked with, switching between the IDEs has  
always been easy.

Best,
Clemens
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Rails -> Lift

2009-04-09 Thread Clemens Oertel

I don't think it's necessary to make a final decision about your IDE  
at any time. AFAIK, all major IDEs work quite well with Maven's pom  
files, so it's very easy to switch IDEs at any time.

I for instance used NetBeans until last month, when JetBrains updated  
their Scala plugin - then I switched to IntelliJ. The transition was  
very smooth.

So start with any one of the IDEs, and once you've figured out what do  
don't like about that very IDE, you can look around whether another  
IDE might do it better.

And anyways, if there really was a "best" IDE, it would probably be  
the only IDE (the causality goes both ways). It's always a matter of  
needs, prior experience, taste ...

Best,
Clemens

On 9-Apr-09, at 5:38 AM, Alexander Kellett wrote:

>
> actually my biggest blocker (and still my blocker) is getting a
> working coding environment.
>
> there is so much contradictory information on which ide is the best.
> it would be really nice to have a document that talks about the pro's
> and con's of each ide.
>
> in the rails/osx world its easy: use textmate unless you have a
> predisposition for something else.
>
> not the case for lift / scala in general.
>
> i know, boring... but i think it really would help to have such a
> document to help people decide.
>
> On Thu, Apr 9, 2009 at 5:58 AM, Charles F. Munat   
> wrote:
>>
>> I'm writing a proposal for a presentation on moving from Rails to  
>> Lift.
>>
>> A couple of stumbling blocks that I've mentioned are:
>>
>> 1. Understanding and taking advantage of immutable constructs.
>>
>> 2. Getting the hang of the view-centric approach to MVC.
>>
>> Before I go much further, I'd like to poll this list for things that
>> others think should be included. For former or current Rails  
>> developers
>> like myself, What sorts of things gave you the most trouble when  
>> moving
>> to Lift (or trying it out)? What would you like to have had someone
>> explain to you to make the transition easier?
>>
>> Thanks for any help!
>>
>> Chas.
>>
>>>
>>
>
> >


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Good way to implement "cancel" links?

2009-04-05 Thread Clemens Oertel
Thanks, David.

Just for my understanding: Links generated by SHtml.link are valid  
throughout the entire session?

For a multi-page form, storing the referrer in the first step in a  
RequestVar would then also work, I take it.

Thank you,
Clemens

On 4-Apr-09, at 6:41 PM, David Pollak wrote:

> S.referer.map(from => SHtml.link("cancel", () => redirectTo(from)))  
> openOr Text("")
>
> On Sat, Apr 4, 2009 at 3:20 PM, Clemens Oertel  > wrote:
>
> Hi,
>
> What's the best way to get generic "Cancel" links into forms, lift-
> style? Assuming that a form can be called from different pages in the
> application, and the cancel link should return to the originating  
> page?
> Would it work to have a RequestVar for the target of the cancel link,
> and populate it using the linking page's URI:
> SHtml.link(editUrl, () => {...; cancelLinkRV(S.request.uri)},
> Text("Edit"))
>
> Is the URI really reusable like this?
>
> Or is there already some better way provided by lift?
>
> Thanks,
> Clemens
>
>
>
>
>
>
> -- 
> Lift, the simply functional web framework http://liftweb.net
> Beginning Scala http://www.apress.com/book/view/1430219890
> Follow me: http://twitter.com/dpp
> Git some: http://github.com/dpp
>
> >

Clemens Oertel
clem...@oertel.ca





Clemens Oertel
clem...@oertel.ca




--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Good way to implement "cancel" links?

2009-04-04 Thread Clemens Oertel

Hi,

What's the best way to get generic "Cancel" links into forms, lift- 
style? Assuming that a form can be called from different pages in the  
application, and the cancel link should return to the originating page?
Would it work to have a RequestVar for the target of the cancel link,  
and populate it using the linking page's URI:
SHtml.link(editUrl, () => {...; cancelLinkRV(S.request.uri)},  
Text("Edit"))

Is the URI really reusable like this?

Or is there already some better way provided by lift?

Thanks,
Clemens


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Forms & validation formatter

2009-04-02 Thread Clemens Oertel
One follow up question, relating to the contexts I mentioned earlier:  
Following my approach mentioned below, let's assume I have a template  
for embedding. This template contains  the HTML code for a tabular  
list of data entities. Depending on where the template is embedded,  
some of the entities' fields should appear as links: There are 2  
linkable reference fields A and B, and depending on the context,  
either A, B, or A and B should be rendered as links to the referenced  
entity.

This logic obviously can't go into the template. Also, the model's  
toForm method is unsuitable (having the model referring to a  
RequestVar seems evil to me). No no, this should go into the snippet,  
where such logic belongs. But this would mean having to go through the  
templates XML tree before calling Site.toForm(site, form), enclosing  
all affected liftf:field elements with the respective links. This  
sounds very, very wrong.

Thus, from my current understanding, this context-sensitive rendering  
of fields is best done using the explicit lift-tag/bind approach. So  
I'll probably have to have explicit bind calls anyways, and won't be  
able to use my initial approach of having the mapper class (or it's  
companion object) fill out the forms itself.

I'd be happy if someone could prove me wrong ...

Best,
Clemens

PS: Exercise for the reader: Instead of selective linking, have only  
either A or B be displayed, depending on the embedding context.

On 31-Mar-09, at 3:59 PM, marius d. wrote:

>>
>>  Outer Template 
>> 
>>Create a New Site
>>
>>
>>  
>>
>>  
>>Submit
>>  
>>
>>
>>  
>>
>> 
>>  End Outer Template 
>>
>>  Embedded Template 
>> 
>> 
>>  Name:> td>
>>  A Hospital Site
>>  
>> 
>> 
>>  End Embedded Template 
>>
>>  SiteOps 
>>def add(form: NodeSeq): NodeSeq = {
>>  val invokedAs = S.invokedAs
>>  val site = Site.create
>>
>>  def newSite(form: NodeSeq): NodeSeq = {
>>def saveMe(): Unit = {
>>  site.validate match {
>>case Nil => site.save ; S.notice("Added " + site.name);
>> S.redirectTo("/sites/")
>>case xs => S.error(xs) ; S.mapSnippet(invokedAs, newSite)
>>  }
>>}
>>
>>bind("site", Site.toForm(site, form), "submit" ->
>> submit("Save", saveMe))
>>  }
>>
>>  newSite(form)
>>}
>>  End SiteOps 
>>
>> The Site.toForm function is pretty much the same as found in
>> MetaRecord. It will eventually call each fields' toForm function
>> (which are the original Lift 1.0 mapper versions, no changes there).
>>
>> Am I really doing things outside the rendering pipeline (this is  
>> not a
>> rhetorical question)?
>
> Nope sorry ... I misunderstood your case. By bad entirely.
>
> It all seems to work, incl. validation.
>> Also, the eagerly evaluated template, which will be passed to toForm,
>> contains only field tags, no other lift tags.
>>
>> Again, imagine a few dozen different entities, each with a ton of
>> fields. I'm sure you'll understand that I'm hesitant to bind each
>> field manually (once for the list page, once for the display page,
>> once for the add page, and again once for the edit page, even though
>> the last 2 can surely be combined into one bind call in the code).
>> I obviously have to declare each field in the model, and refer to it
>> in the view. I really wouldn't mind not having to mention it anywhere
>> inbetween.
>
> This is actually a nice thing to do. Sorry that I misunderstood your
> intentions :)
>
>>
>> Thank you for all your help,
>> Clemens
>>
>> Clemens Oertel
>> clem...@oertel.ca
> >

Clemens Oertel
clem...@oertel.ca



Clemens Oertel
clem...@oertel.ca




--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] MappedDateTime - Do we have a Date? Or is it a timestamp?

2009-03-31 Thread Clemens Oertel

While trying to figure out why my MappedDateTime fields get stored in  
the DB with all the time info set to 0, I noticed the following:

MappedDateTime (v. 1.0) "claims" to be a TimeStamp: def targetSQLType  
= Types.TIMESTAMP. However, it uses java.sql.Date for its JDBC- 
friendly converted version, not java.sql.TimeStamp. If I read the  
java.sql.Date documentation correctly, java.sql.Date does set all time  
information to 0, since the SQL DATE type only stores dates, by no  
times.

Any comment whether this might have something to do with me losing my  
time would be appreciated.

Best,
Clemens

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Forms & validation formatter

2009-03-31 Thread Clemens Oertel

Marius:

On 31-Mar-09, at 12:31 PM, marius d. wrote:

>
>
>
> On Mar 31, 5:06 pm, Clemens Oertel  wrote:
>> - Why not provide the same template mechanism used for forms for HTML
>> output? This way I can reuse the same template for both - given that
>> my records have at least dozens, if not even hundreds, of fields,
>> that'd be a great help.
>
> Well you can load templates from an html file. Please see
> LiftSession.findAnyTemplate function.

just thought that, since MetaRecord has

def toForm(inst: BaseRecord): NodeSeq
and
def toForm(inst: BaseRecord, template: NodeSeq): NodeSeq

it would only be consistent to provide similar means for HTML output.

> Well I can understand the urge but we do NOT recommend processing
> templates outside of rendering pipeline. You can call
> LiftSession.processSurroundAndInclude so that lift tags to be
> processed etc. but again it is not recommended. The main reason is
> that your functions that you assume to be bounded during this off-
> cycle template processing, will not actually be bounded cause it i
> happening in the wrong place.
>
> The Record's form template is to allow you to shape the form in any
> way you like (from markup perspective). But this template is supposed
> to be very very lightweight in terms of lift's tags. It is just an
> xhtml fragment and not a full blow page/(lift template).

Mmh, maybe there's a misunderstanding. I was only using the template  
as indicated in the source code, or so I thought.

May I just provide an abbreviated version of the code that I come up  
with?

 Outer Template 

   Create a New Site

   
 
   
 
   Submit
 
   
   
 
   

 End Outer Template 

 Embedded Template 


 Name:
 A Hospital Site
 


 End Embedded Template 

 SiteOps 
   def add(form: NodeSeq): NodeSeq = {
 val invokedAs = S.invokedAs
 val site = Site.create

 def newSite(form: NodeSeq): NodeSeq = {
   def saveMe(): Unit = {
 site.validate match {
   case Nil => site.save ; S.notice("Added " + site.name);  
S.redirectTo("/sites/")
   case xs => S.error(xs) ; S.mapSnippet(invokedAs, newSite)
 }
   }

   bind("site", Site.toForm(site, form), "submit" ->  
submit("Save", saveMe))
 }

 newSite(form)
   }
 End SiteOps 

The Site.toForm function is pretty much the same as found in  
MetaRecord. It will eventually call each fields' toForm function  
(which are the original Lift 1.0 mapper versions, no changes there).

Am I really doing things outside the rendering pipeline (this is not a  
rhetorical question)? It all seems to work, incl. validation.
Also, the eagerly evaluated template, which will be passed to toForm,  
contains only field tags, no other lift tags.

Again, imagine a few dozen different entities, each with a ton of  
fields. I'm sure you'll understand that I'm hesitant to bind each  
field manually (once for the list page, once for the display page,  
once for the add page, and again once for the edit page, even though  
the last 2 can surely be combined into one bind call in the code).
I obviously have to declare each field in the model, and refer to it  
in the view. I really wouldn't mind not having to mention it anywhere  
inbetween.

Thank you for all your help,
Clemens


Clemens Oertel
clem...@oertel.ca




--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Forms & validation formatter

2009-03-31 Thread Clemens Oertel
p, it's fixed
>> requirements.
>>
>> At field level, there are also different possible representations.  
>> For
>> example, I would like to be able to represent a record as a tabular
>> form, with every input field being shown with its preferred length.  
>> In
>> addition to this, I would like to have a different form with a fixed
>> with multi-column layout; for this form, no input field must be wider
>> than 40 characters. Somehow I have to tell the fields not to make
>> themselves wider than 40 characters, and not just use the maximum
>> length.
>>
>> Again, what it boils down to is the desire to be able to have
>> different representations for a single record, and to have different
>> possible representations for each field. This while maintaining as
>> much encapsulation as possible.
>
> Well for both mapper and record you have the toForm function which is
> per field thus allows you to represent the field in any way you like:
> your own Node, augment the default node with new attributes etc. And
> your implementation can of choose the layout based on your own
> context.
>
>>
>> Hence my original idea to have fields provide representation hints
>> (eg. "I'd like to be 80 characters wide"), and then have another
>> "something" that uses these hints for the actual output, while
>> potentially adding additional hints/constrains (eg. "No one get's  
>> more
>> than 40 characters"), css directives, a little red star in front of
>> mandatory fields (based on a rendering hint),  Depending on how
>> the record is being displayed, I would use a different "something",
>> and neither the record nor the fields would have to know anything
>> about "application context".
>
> Well since you can override the toForm for each field you can add your
> own "something" to it.  Thus you can work with necessary abstractions
> to make the field "unaware" of the "application context" if that's
> what you want but it feels to me that this is an application specific
> concern and not a framework one. Personally if I'd need to render a
> record/field in different layouts using mapper I'd probably make the
> fields aware of the context in which they need to render themselves.
> Context is good ! :)
>
>>
>> If I then had a default "something", which renders fields the way  
>> they
>> are rendered right now, and have the various record fields
>> (StringField, etc.) call upon this default "something" whenever their
>> toForm-function is called, no one would notice something has changed.
>> But I could also call toForm(formRenderer) for non-default rendering.
>>
>>> it's quire a paradigm shift from ... say MVC mindset. But let's not
>>> get into a "patterns" debate now .. we had plenty of those :)
>>
>> Agreed.
>>
>> Best,
>> Clemens
> >

Clemens Oertel
clem...@oertel.ca





Clemens Oertel
clem...@oertel.ca




--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Forms & validation formatter

2009-03-18 Thread Clemens Oertel
I admit to only having worked with mapper. I will look closer into  
record, (quick glance: it comes with next-to-the-field messages, nice).

Marius, are you referring to the toForm functions? I'm probably just  
not seeing how to use them in a flexible manner. With respect to  
validation, I was wondering how to apply conditional formatting based  
on failed/succeeded validation.

Maybe a word or two to the background of my questions: I'm currently  
trying to port a web application from RoR to lift. All I know is that  
RoR does not work for me any longer, but I'm not sure where to go yet,  
so I started to look around, and lift seems to be the most promising  
candidate. The heavy exposure to RoR might have tainted my mind, true,  
and I'm open to be shown the light.

Anyways, this app is of medical nature, very database heavy, lots and  
lots of fields. In order to avoid error upon data entry, the record's  
form on screen must looks as closely like the paper version as  
possible. A record's field can appear (and may be edited) in different  
contexts. Sometimes, the same text field is displayed with different  
lengths, the same text area may have different heights, all text  
fields may be limited to a max length of n in some contexts, etc.

Other aspect of the story: While working on the RoR version, the  
directive was: Some boolean fields are to be displayed as drop downs  
with 3 values (empty, yes, no). This now has changed, these boolean  
fields are to be displayed as 3 radio buttons. One of course wants to  
ensure that such a change only affects one area in the code base.

That's what got me wondering: Is the toForm approach the best one for  
my case?

Thanks for listening,
Clemens



On 18-Mar-09, at 3:18 AM, marius d. wrote:

>
> FWIW please also take a look on Record and form&validation support.
>
> Br's,
> Marius
>
> On Mar 17, 11:07 pm, Clemens Oertel  wrote:
>> Hello everybody,
>>
>> Still trying to learn how to use lift efficiently and effectively, I
>> got a little bit confused about the toForm function in the model/
>> mappers. Admittedly, my web framework background may be limited, but
>> this looked to me as if some view code snuck into the model space
>> there (I must admit that I do like how RoR tries to keep the models
>> fairly clean of both controller  code and of view code).
>>
>> For my first little project, I was going to encapsulate the HTML  
>> field
>> formatting into a separate class (similar to what RoR does, but  
>> making
>> use of the type system).
>>
>> This is a very quick brain dump, not running code.
>>
>> // The different field types, at a higher level than HTML
>> abstract class InputType
>> case class TextField extends InputType
>> case class DateField extends InputType
>> case class DateTimeField extends InputType
>>
>> // Rendering hints that an form field formatter may use, could also  
>> be
>> called FormGenerator ...
>> abstract class RenderingHint
>> case class MinLength(l: Int) extends RenderingHint
>> case class MaxLength(l: Int) extends RenderingHint
>>
>> // Input-type aware callback'ed formatter, from the model's  
>> perspective
>> trait InputTypeHandler {
>>def handleTextField(fieldID: String, presetValue: String,
>> renderingHints: RenderingHint*)
>>
>>def handleDateField(fieldID: String, presetValue: Date,
>> renderingHints: RenderingHint*)
>>
>> }
>>
>> // A model class using the callback
>> class ModelClass {
>>object aField extends MappedString(this, 128) {
>>  def inputTypeCallback(InputTypeHandler handler) {
>>// A reasonable default should/could be pushed upwards in the
>> type hierarchy
>>handler.handleTextField(fieldID, this.is,  
>> MaxLength(this.length))
>>  }
>>}
>>
>> }
>>
>> This InputTypeHandler could be a nice spot to deal with validation
>> result formatting:
>>
>> class AnInputFormatter(errors: List[FieldError]) extends
>> InputTypeHandler {
>>def handleTextField(fieldID: String, presetValue: String,
>> renderingHints: RenderingHint*) {
>>  errors.filter(_._1 == fieldID).match {
>>case Nil => /* format field normally */
>>case xs => /* format as error, i.e. red background, error
>> messages right of field  */
>>  }
>>}
>>
>>...
>>
>> }
>>
>> // A snippet
>> ...
>> val inputFormatter = new AnInputFormatter(errorsFromValidation)
>> bind("form", html, "aField" -> aModelClass.aFie

[Lift] Forms & validation formatter

2009-03-17 Thread Clemens Oertel

Hello everybody,

Still trying to learn how to use lift efficiently and effectively, I  
got a little bit confused about the toForm function in the model/ 
mappers. Admittedly, my web framework background may be limited, but  
this looked to me as if some view code snuck into the model space  
there (I must admit that I do like how RoR tries to keep the models  
fairly clean of both controller  code and of view code).

For my first little project, I was going to encapsulate the HTML field  
formatting into a separate class (similar to what RoR does, but making  
use of the type system).

This is a very quick brain dump, not running code.

// The different field types, at a higher level than HTML
abstract class InputType
case class TextField extends InputType
case class DateField extends InputType
case class DateTimeField extends InputType

// Rendering hints that an form field formatter may use, could also be  
called FormGenerator ...
abstract class RenderingHint
case class MinLength(l: Int) extends RenderingHint
case class MaxLength(l: Int) extends RenderingHint

// Input-type aware callback'ed formatter, from the model's perspective
trait InputTypeHandler {
   def handleTextField(fieldID: String, presetValue: String,  
renderingHints: RenderingHint*)

   def handleDateField(fieldID: String, presetValue: Date,  
renderingHints: RenderingHint*)
}

// A model class using the callback
class ModelClass {
   object aField extends MappedString(this, 128) {
 def inputTypeCallback(InputTypeHandler handler) {
   // A reasonable default should/could be pushed upwards in the  
type hierarchy
   handler.handleTextField(fieldID, this.is, MaxLength(this.length))
 }
   }
}

This InputTypeHandler could be a nice spot to deal with validation  
result formatting:

class AnInputFormatter(errors: List[FieldError]) extends  
InputTypeHandler {
   def handleTextField(fieldID: String, presetValue: String,  
renderingHints: RenderingHint*) {
 errors.filter(_._1 == fieldID).match {
   case Nil => /* format field normally */
   case xs => /* format as error, i.e. red background, error  
messages right of field  */
 }
   }

   ...
}

// A snippet
...
val inputFormatter = new AnInputFormatter(errorsFromValidation)
bind("form", html, "aField" -> aModelClass.aField.  
inputTypeCallback(inputFormatter))
...

Maybe a partial function, potentially on case classes, is better? Many  
options ...

I'm looking forward to any feedback.

Best,
Clemens

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---