[Lift] Record-aware secondary menu?
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?
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
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
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 c...@munat.com 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] Good way to implement cancel links?
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
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 lift:surround with=default at=content h2Create a New Site/h2 lift:snippet type=SiteOps.add form=post eager_eval=true table tfoot tr td colspan=3site:submitSubmit/site:submit/td /tr /tfoot lift:embed what=/sites/_site / /table /lift:snippet /lift:surround End Outer Template Embedded Template tbody tr tdliftf:field_label name=nameName/liftf:field_label:/ td tdliftf:field name=nameA Hospital Site/liftf:field/td tdliftf:field_msg name=name //td /tr /tbody 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] Re: Forms validation formatter
Hello, Sorry for the delay in my response, but I only get to play with lift on the weekends, and I wanted to look into your suggestions in more detail. I ported the toForm code from Record to Mapper (and by port, I mean mostly cut'n'paste). While doing so, I noticed 2 things: - 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. - The templates require the use of lift:field and similar tags. I thought I'd be really smart, and created a HTML file A with lift-tags (lift:SomeClass.add.../lift:SomeClass.add) to run my snippet, and used the lift:field tags as children to lift:SomeClass.add. This way, I can create my templates externally, and use the normal lift dispatch-from-view mechanism. And, to save me some more work, the actual form template is in a separate, reusable, HTML file B, to be embedded into A. Embedding, of course, requires eager evaluation. Fine. No. With eager evaluation, lift of course complains that there is no class field, as referenced by lift:field. Now me's wondering whether a separate namespace would be more appropriate? (I did switch to a different namespace, liftf, out of necessity, but I figure that other people might have similar issues) As to the original discussion: I still strongly believe that toForm and to/as(X)Html should not be in Mapper/Record. Different story for JSON/XML/SQL - those seem to me to be rather functionality complete, no problem. But form and html creation seem to be something that most users will want to adapt to their application's needs eventually - state dependent css classes, javascript validation, AJAX form updates... In the examples that I've seen so far, this functionality was dealt with in the snippet. So, either mapper/record eventually become this super- omnipotent-mega-classes that can deal with this functionality to (field.toJavaScriptValidatingAndIncrementallyAjaxUpdatingForm ...), or form/html generation happens in multiple locations, or the user has to override some functions from mapper/record/fields. My beef with this is A) that the respective function calls, given their current signature, require the respective mapper/record-objects to be fully aware of application state for more complex applications; and B) that it is my understanding that overriding internal classes of a framework is a bad thing - I'd rather see a proper application of the Hollywood principle. Just wanted to provide an outsider's feedback. Overall, I think lift's just fantastic. Thank you for listening/reading, Clemens On 19-Mar-09, at 1:08 PM, marius d. wrote: On Mar 18, 11:24 pm, Clemens clemens.oer...@gmail.com wrote: Thank you for your patience, Marius. Well you can use different RecordMeta implementations if you need to different representation of a record without sequential template change. So no state dependency. , b I'm really not trying to be difficultut having multiple RecordMeta instances, for which the HTML output seems to be only one of many functionalities, seems to be shooting with canons at sparrows. Having a toForm functions that takes some template provider as input could be one option. Well this is kinda already in there but it's private :) ... See: private def _toForm(inst: BaseRecord, template: NodeSeq): NodeSeq so to me makes sense to relax it ... to public def toForm(inst: BaseRecord, template: NodeSeq): NodeSeq ... thanks for reminding me about this :) Anyways, I was not even thinking at record level, but rather at field level. See below. Well keeping close view representation and backend abstraction makes a lot of sense as it reduces lots of complexity. Having records/ mappers that know how to represent themselves in different contexts (DB, xhtml) brings a lot of benefits an simplicity. I admit thought that (Btw, by context I meant different HTML display contexts.) I agree that a field should be able to provide hints about how it should be represented, such as max/min length, type, defaults, etc. Depending on the logical context within the app I'm working on, a record (and thus its fields) can have multiple representations: row in a table, complete record as a table, abbreviated record as a table, complete form as table, form as row in a table, form with mandatory fields only, records have to be printed out as ini-files, etc. Unfortunately, it's not me making this stuff up, 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
[Lift] Re: Forms validation formatter
Marius: On 31-Mar-09, at 12:31 PM, marius d. wrote: On Mar 31, 5:06 pm, Clemens Oertel clemens.oer...@gmail.com 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 lift:surround with=default at=content h2Create a New Site/h2 lift:snippet type=SiteOps.add form=post eager_eval=true table tfoot tr td colspan=3site:submitSubmit/site:submit/td /tr /tfoot lift:embed what=/sites/_site / /table /lift:snippet /lift:surround End Outer Template Embedded Template tbody tr tdliftf:field_label name=nameName/liftf:field_label:/td tdliftf:field name=nameA Hospital Site/liftf:field/td tdliftf:field_msg name=name //td /tr /tbody 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] MappedDateTime - Do we have a Date? Or is it a timestamp?
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
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 formvalidation support. Br's, Marius On Mar 17, 11:07 pm, Clemens Oertel clemens.oer...@gmail.com 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.aField. inputTypeCallback(inputFormatter)) ... Maybe a partial function, potentially on case classes, is better? Many options ... I'm looking forward to any feedback. 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
Yes I am referring to toForm but note that you can provide your own template. Please see formTemplate. I did, thanks for the pointer. formTemplate applies to the record as a whole, right? If I want to render a record differently, I could set different templates one after the other - even though this introduces more evil state dependence. Just trying to figure out how to how to solve my case where a field is supposed to be rendered differently in different contexts - a single asXHtml variable doesn't seem to allow this. Also, all the formatting happens in what I thought was the DB abstraction layer, which still makes context-sensitive formatting difficult (again, as I understand things right know) - it's just personal style, but I like to keep control flow and view stuff outside my data models. But record promises to give me a lot more flexibility than mapper, that's great. I think the existent scaladocs can be quite helpful. Point taken ;-) Nevertheless for youimediate needs the Record is probably not very relevant yet as DB for Recrd is not yet implemented. I was just pointing out that formsform validations are consistently provided by Record. I think there is still some level of validation in mappers but I haven't played with it yet ... Oh, the validation is working just fine with mapper. It's only the lack of flexibility with respect to automated output that's I'm talking about. 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
Thank you for your patience, Marius. Well you can use different RecordMeta implementations if you need to different representation of a record without sequential template change. So no state dependency. I'm really not trying to be difficult, but having multiple RecordMeta instances, for which the HTML output seems to be only one of many functionalities, seems to be shooting with canons at sparrows. Having a toForm functions that takes some template provider as input could be one option. Anyways, I was not even thinking at record level, but rather at field level. See below. Well keeping close view representation and backend abstraction makes a lot of sense as it reduces lots of complexity. Having records/mappers that know how to represent themselves in different contexts (DB, xhtml) brings a lot of benefits an simplicity. I admit thought that (Btw, by context I meant different HTML display contexts.) I agree that a field should be able to provide hints about how it should be represented, such as max/min length, type, defaults, etc. Depending on the logical context within the app I'm working on, a record (and thus its fields) can have multiple representations: row in a table, complete record as a table, abbreviated record as a table, complete form as table, form as row in a table, form with mandatory fields only, records have to be printed out as ini-files, etc. Unfortunately, it's not me making this stuff up, 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. 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. 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 --~--~-~--~~~---~--~~ 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] lift:snippet type=Foo.bar != lift:Foo.bar?
Hello everybody, I'm fairly new to lift (and to scala, to be honest), and just trying to find my way around. So far I like what I'm seeing and deing, but some things keep me puzzled. Short version of my confusion: Is lift:snippet type=SiteOps.add form=post.../lift:snippet equivalent to lift:SiteOps.add.../lift:SiteOps.add ? Long version: I was trying to implement a typical entry-form for database entities. The model classes for the database entities have a variety of verification checks. When checks fail, the form should be redisplayed, with the previously entered (and probably erroneous) values filled in. My snippet is pretty much a mixture of the various examples and the starter guide: def add(form: 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, form, name - site.name.toForm, abbreviation - site.abbreviation.toForm, submit - SHtml.submit(New, saveMe)) } newSite(form) } With the lift:snippet type=SiteOps.add form=post style tags, everything works as expected (form fields are populated after a failed validation). If I use lift:SiteOps.add, the form comes up empty after a failed validation. What am I getting wrong? Thanks in advance! 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: lift:snippet type=Foo.bar != lift:Foo.bar?
That's good to hear - I like orthogonality. I created a ticket for this, #21. Thanks Clemenns On Mar 17, 12:26 pm, David Pollak feeder.of.the.be...@gmail.com wrote: lift:snippet type=SiteOps.add form=post == lift:SiteOps.add form=post If this is not the case, it's a Lift defect. On Tue, Mar 17, 2009 at 8:41 AM, Clemens clemens.oer...@gmail.com wrote: Hello everybody, I'm fairly new to lift (and to scala, to be honest), and just trying to find my way around. So far I like what I'm seeing and deing, but some things keep me puzzled. Short version of my confusion: Is lift:snippet type=SiteOps.add form=post.../lift:snippet equivalent to lift:SiteOps.add.../lift:SiteOps.add ? Long version: I was trying to implement a typical entry-form for database entities. The model classes for the database entities have a variety of verification checks. When checks fail, the form should be redisplayed, with the previously entered (and probably erroneous) values filled in. My snippet is pretty much a mixture of the various examples and the starter guide: def add(form: 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, form, name - site.name.toForm, abbreviation - site.abbreviation.toForm, submit - SHtml.submit(New, saveMe)) } newSite(form) } With the lift:snippet type=SiteOps.add form=post style tags, everything works as expected (form fields are populated after a failed validation). If I use lift:SiteOps.add, the form comes up empty after a failed validation. What am I getting wrong? Thanks in advance! Best, Clemens -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Git some:http://github.com/dpp --~--~-~--~~~---~--~~ 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] Forms validation formatter
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 -~--~~~~--~~--~--~---
[Lift] Forms validation formatter
Hello everybody, (I sent this post once already a few hours ago, but it has not shown up yet, so I decided to send it again. I apologize should it show up twice.) 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 -~--~~~~--~~--~--~---