Thanks for the fast response! Okay, a couple of things:
1.
> Well, typically the form callbacks are just setting values. If they're more 
> ...
(I take that to mean that setting entity properties does not require a
transaction? I thought that in JPA entities are generally monitored
for modifications? Is that a mistake?)
Look at my code for setting the location.
def bindLocation(loc: NatureLocationType) = {
      var l = loc
      bind("location", chooseTemplate("each", "location", xhtml),
      "id" -> SHtml.hidden(()=> l = NatureLocationType.lookup
(loc.id)),
      "name" -> SHtml.text(l.name, l.name = _),
      "allowStreet" -> SHtml.checkbox(l.allowStreet, l.allowStreet =
_),
      "allowHospital" -> SHtml.checkbox(l.allowHospital,
l.allowHospital = _),
      "allowDoctor" -> SHtml.checkbox(l.allowDoctor, l.allowDoctor =
_),
      "allowEquipment" -> SHtml.checkbox(l.allowEquipment,
l.allowEquipment = _),
      "removeBtn" -> SHtml.submit(?("Remove"), ()=>removeLocation(l))
      )
    }
Because the entity manager is closed after each request, the location
has to be reloaded in order to be modified. So loading it has to be
done in a transaction, but can I end the transaction before I set the
properties?

2.
In the mean time I made my own whole-form processor. Unfortunately
it's a little verbose to use.
Here's the code (currently only supports text boxed and check boxes,
and string values and boolean values, but it's very easy to extend):

import scala.xml.{Group, Elem, NodeSeq}
import scala.collection.mutable.{Map => mMap}

import net.liftweb.http.SHtml
import net.liftweb.util.{Helpers, Full, Empty}
import Helpers._


abstract class FormProcessor(prefix: String) {
  def text(attrs: (String, String)*)(init: String, action:
String=>Unit) = SHtml.text(init, action, attrs:_*)
  def text: (String,String=>Unit)=>NodeSeq  = text()_
  def checkbox(attrs: (String, String)*)(init: Boolean, action:
Boolean=>Unit) = SHtml.checkbox(init, action, attrs:_*)
  def checkbox: (Boolean, Boolean=>Unit)=>NodeSeq = checkbox()_

  val stringValues: mMap[String, String] = mMap.empty[String, String]
  val strings = mMap.empty[String, (String,String=>Unit)=>NodeSeq]

  val booleanValues = mMap.empty[String, Boolean]
  val booleans = mMap.empty[String, (Boolean,Boolean=>Unit)=>NodeSeq]

  def bind(xhtml: NodeSeq) = {
    def transform(node: NodeSeq): NodeSeq = {
      put
      node match {
        case Elem(`prefix`, label, _, _, _*) if strings.keys contains
label =>
          strings(label)(stringValues(label), stringValues(label) = _)
        case Elem(`prefix`, label, _, _, _*) if booleans.keys contains
label =>
          booleans(label)(booleanValues(label), booleanValues(label) =
_)
       case other => other
      }
    }
    Helpers.bind(prefix, Full(transform _), Empty, xhtml) ++
      Seq(SHtml.hidden(()=>get))

  }

  def put: Unit
  def get: Unit
}

And here's some usage:
    def bindLocation(loc: NatureLocationType) = {
      var l = loc
      val form = new lrbcol.FormProcessor("location") {
        strings += ("name" -> text)
        booleans ++= Map("allowStreet"->checkbox,
                         "allowHospital"->checkbox,
                         "allowDoctor"->checkbox,
                         "allowEquipment"->checkbox)
        def put {
          stringValues("name") = l.name
          booleanValues ++= Map("allowStreet" -> l.allowStreet,
                                "allowHospital" -> l.allowHospital,
                                "allowDoctor" -> l.allowDoctor,
                                "allowEquipment" -> l.allowEquipment)
        }
        def get = transaction {
          val l = NatureLocationType.lookup(loc.id)
          l.name = stringValues("name")
          l.allowStreet = booleanValues("allowStreet")
          l.allowHospital = booleanValues("allowHospital")
          l.allowDoctor = booleanValues("allowDoctor")
          l.allowEquipment = booleanValues("allowEquipment")
        }
      }

      bind("location",
           form.bind(chooseTemplate("each", "location", xhtml)),
           "removeBtn" -> SHtml.submit(?("Remove"), ()=>removeLocation
(NatureLocationType.lookup(loc.id)))
      )
    }
If you have a better way of implementing it, let me know. Feel free to
include it in lift, unmodified or modified.


3.
I'll put it in the next post because it's somewhat separate.

On May 19, 3:20 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> Well, typically the form callbacks are just setting values. If they're more
> complex than that then you would need a try/catch in each function. I don't
> think that the current form processing code has any facility for a per-form
> exception handler, although that might be a useful feature.
>
> Derek
>
> On Tue, May 19, 2009 at 1:09 PM, ngug <naftoli...@gmail.com> wrote:
>
> > Sorry for the delay in responding. My question was not about
> > transaction API, my question was a practical one: If form processing
> > is split into a bunch of little anonymous functions, how can you put
> > them in a try/finally?
>
> > On May 15, 1:59 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> > > EntityManager has a getTransaction method that you can use along with the
> > > constructor I mentioned previously to explicitly begin and end
> > transactions
> > > in your code.
> def bindLocation(loc: NatureLocationType) = {
      var l = loc
      bind("location", chooseTemplate("each", "location", xhtml),
      "id" -> SHtml.hidden(()=> l = NatureLocationType.lookup
(loc.id)),
      "name" -> SHtml.text(l.name, l.name = _),
      "allowStreet" -> SHtml.checkbox(l.allowStreet, l.allowStreet =
_),
      "allowHospital" -> SHtml.checkbox(l.allowHospital,
l.allowHospital = _),
      "allowDoctor" -> SHtml.checkbox(l.allowDoctor, l.allowDoctor =
_),
      "allowEquipment" -> SHtml.checkbox(l.allowEquipment,
l.allowEquipment = _),
      "removeBtn" -> SHtml.submit(?("Remove"), ()=>removeLocation(l))
      )
    }
> > > derek
>
> > > On Fri, May 15, 2009 at 11:45 AM, ngug def bindLocation(loc: 
> > > NatureLocationType) = {
      var l = loc
      bind("location", chooseTemplate("each", "location", xhtml),
      "id" -> SHtml.hidden(()=> l = NatureLocationType.lookup
(loc.id)),
      "name" -> SHtml.text(l.name, l.name = _),
      "allowStreet" -> SHtml.checkbox(l.allowStreet, l.allowStreet =
_),
      "allowHospital" -> SHtml.checkbox(l.allowHospital,
l.allowHospital = _),
      "allowDoctor" -> SHtml.checkbox(l.allowDoctor, l.allowDoctor =
_),
      "allowEquipment" -> SHtml.checkbox(l.allowEquipment,
l.allowEquipment = _),
      "removeBtn" -> SHtml.submit(?("Remove"), ()=>removeLocation(l))
      )
    } <naftoli...@gmail.com> wrote:
>
> > > > One entity group per transaction is a GAE requirement. But my question
> > > > about handling transactions was more specific - because form
> > > > processing is specified "piecemeal" in separate closures, you can't
> > > > use the normal try/finally. It seems a little too much effort to
> > > > create a hidden field before and after every form/"subform".
> > > > Thanks.
> > > > P.S. Sorry about the triple post. Opera Mobile (well, Google) didn't
> > > > tell me the post was successful like it usually does, so I thought it
> > > > didn't go through. (I thought the list is moderated and you would
> > > > filter the extras just in case.)

--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to