(Note: I submitted a response to this Google group a while ago, but it
hasn't appeared yet, ~4 hours later, so I'm reposting)

Hello again, and thanks for the solution; it's not obvious at all and
could be very difficult to find a sustainable solution for.
One thing that springs to mind is that you could change the params of
"bind" from (String, NodeSeq) to (String, => NodeSeq) (and BindParam
too of course); then the values will be lazy inside of the bind
implementation and the user won't notice any difference. This breaks
binary compatibility, though, so you might be able to find something
better.

Anyways, thanks for the solution to my little problem!

(PS: you could put "_: NodeSeq" instead of "ignore: NodeSeq" above;
the Scala compiler might be able to optimize the code better then)

On Jun 20, 1:13 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> Okay... this was the hardest problem I've dealt with in a while.
> Lift processed form elements in the order that they are created.  Usually,
> the order that they are created is the order they appear in bind.
>
> However, that is not the case here because the binding to "field" is a
> function that is evaluated when each field element is encountered, but the
> submit button is bound when it's encountered in the bind() method... so the
> submit button gets bound before the form elements and because of that the
> functions for the form elements never get run because the submit does a
> redirect which internally to Lift throws an exception.  The Dog was in fact
> getting saved to the RDBMS, but with its original values.
>
> The short answer on how to fix the problem is to change:
>  def innerEdit = bind("dog", xhtml,
>       "field" -> ((x: NodeSeq) => localForm(x, dogToEdit)),
>       "submit" ->  SHtml.submit("Edit", testEdit _))
>
> to:
>
>  def innerEdit = bind("dog", xhtml,
>       "field" -> ((x: NodeSeq) => localForm(x, dogToEdit)),
>       "submit" -> ((ignore: NodeSeq) => SHtml.submit("Edit", testEdit _)))
>
> The submit button will be evaluated lazily and last.  This will fix the
> problem.
>
> Now... I have to figure out what to do in the broader case because the lazy
> vs. strict evaluation will cause this subtle thing to happen again and again
> and it's amazingly non-trivial to figure it out.
>
> Thanks,
>
> David
>
> 2009/6/19 dflemstr <david.flemst...@gmail.com>
>
>
>
> > Hello again,
> > thank you so much for your time. My fork is located here:
> > git://github.com/dflemstr/lift_1_1_sample.git
>
> > The code is very straightforward and I removed all unnecessary
> > constructs (such as the User.scala file) so it should be really clear
> > what the problem is now.
>
> > On Jun 19, 7:06 pm, David Pollak <feeder.of.the.be...@gmail.com>
> > wrote:
> > > 2009/6/19 dflemstr <david.flemst...@gmail.com>
>
> > > > Well, OK, I'm sorry everyone, I should have been more clear:
> > > > The goal that I have is to make a snippet that creates a templated
> > > > edit form for me. However, this is not the >issue< which I want to
> > > > discuss. The issue is that when I try to make this snippet (and this
> > > > could have been any snippet, since the principles are the same), I am
> > > > unable to, because somewhere the instance of the Mapper for which I
> > > > want to create the snippet (in this case it's a MetaMegaProtoUser)
> > > > gets lost, and thus no changes are preserved.
>
> > > I am very confused.  I don't understand what "gets lost" means?
>
> > > > The reason why I
> > > > mentioned the templating in the first place is because I basically use
> > > > exactly the same code as in the default MetaMegaProtoUser.edit method,
> > > > just adding some bind calls and an extra parameter: the template
> > > > NodeSeq, and suddenly the code breaks.
>
> > > A compiler error?  An exception? What kind of break do you mean?
>
> > > > As mentioned before, any
> > > > changes I make in the client aren't saved. I have no good way of
> > > > checking whether the changes even are contained within the POST(→it's
> > > > the localForm's fault) or if the User instance gets lost earlier
> > > > (→it's some closure that fails somewhere), but the testEdit function
> > > > gets called for sure, but with the wrong user instance.
>
> > > I think the best thing to do with discuss in code.  I've created a simple
> > > project athttp://github.com/dpp/lift_1_1_sample/tree/master
>
> > > Please fork the repository and enhance the code to edit the Dog object...
> > > your code doesn't have to compile or run, but if I can see where you're
> > > having problems, I can work to resolve them and to help you get over this
> > > hump.  Point out where you're running into problems and I'll fix up the
> > code
> > > to work the way you want it to.
>
> > > Thanks,
>
> > > David
>
> > > > Hopefully I've made my problem more clear.
>
> > > > On Jun 19, 6:19 pm, David Pollak <feeder.of.the.be...@gmail.com>
> > > > wrote:
> > > > > On Fri, Jun 19, 2009 at 3:25 AM, dflemstr <david.flemst...@gmail.com
>
> > > > wrote:
>
> > > > > > Well, that probably is good advice, but doesn't really relate to
> > the
> > > > > > matter at hand if I understand you correctly.
> > > > > > As you may notice, the code is a modified version of the embedded
> > > > > > code, but it's completely independent from it (it doesn't override
> > > > > > anything). It could have been code that had been written completely
> > by
> > > > > > me.
>
> > > > > > And anyways, my goal is to make a snippet out of the edit form, and
> > > > > > not to just be able to load a template from a file (I need to put
> > the
> > > > > > whole edit form in multiple, obscure places) so your solution, I
> > must
> > > > > > say, isn't any help to me. Maybe my original message title was
> > > > > > misleading.
>
> > > > > I am totally confused as to what your goal is?  Is it to put the form
> > > > into a
> > > > > template file (a .html) file?  Is it to control the rendering of the
> > form
> > > > > elements?  Is it something else?
>
> > > > > In terms of ProtoUser, that class is meant as a quick bootstrap to
> > > > getting
> > > > > your project going.  It lends itself nicely to adding fields.  Any
> > > > styling
> > > > > needs to be done via CSS.  If you need something more complex (like
> > ESME
> > > > > does), you can pull the code into your User class and then work to
> > > > achieve
> > > > > the particular goal.  If we can cycle a bit on what your particular
> > goal
> > > > is,
> > > > > I'm sure we can get you there.
>
> > > > > > The issue is that the theUser object isn't preserved between
> > requests.
> > > > > > Apart from that, the snippet could've been any other snippet
> > (because
> > > > > > it's just being used as a generic mapper; I could've created this
> > form
> > > > > > for any structure).
>
> > > > > > Thank you for your effort, anyhow!
>
> > > > > > On Jun 19, 6:21 am, David Pollak <feeder.of.the.be...@gmail.com>
> > > > > > wrote:
> > > > > > > I'd suggest copying/pasting the code from ProtoUser and
> > MegaProtoUser
> > > > and
> > > > > > > munging the code so that you don't have to work around the
> > embedded
> > > > > > > MegaProtoUser code.  Seehttp://
> > > > > > svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/sca...
> > > > > > > I recently made this change to the
>
> > > > > > > On Thu, Jun 18, 2009 at 1:51 PM, dflemstr <
> > david.flemst...@gmail.com
>
> > > > > > wrote:
>
> > > > > > > > Hello everyone,
> > > > > > > > I'm having some problems with making the MetaMegaProtoUser
> > "edit"
> > > > > > > > method templateable (because I believe in the concept of
> > separating
> > > > > > > > content and design) and am succeeding quite well, except for
> > with
> > > > one
> > > > > > > > little detail: I can't make my changes in the edit form
> > persistent;
> > > > it
> > > > > > > > seems that the "User" instance gets lost somewhere in the
> > process
> > > > and
> > > > > > > > that all the client-side changes therefore also get lost.
>
> > > > > > > > The code is at the end of the message. The edit method is
> > called
> > > > with
> > > > > > > > a template which also is at the very end of the message.
>
> > > > > > > > I would really appreciate if anyone with more Lift experience
> > than
> > > > me
> > > > > > > > could spot the mistake, because I simply cannot find it.
>
> > -------------------------------------------------------------------------------------------------
> > > > > > > > The "snippet" (inside a subclass of MetaMegaProtoUser):
>
> > > > > > > >  /** Create an edit form with the specified template */
> > > > > > > >  def edit(xhtml: NodeSeq) = {
> > > > > > > >    val theUser: User = currentUser.open_! // we know we're
> > logged
> > > > in
>
> > > > > > > >    def testEdit() {
> > > > > > > >      theUser.validate match {
> > > > > > > >        case Nil =>
> > > > > > > >          theUser.save
> > > > > > > >          S.notice("Profile updated") //The Lift Core has a
> > spelling
> > > > > > > > mistake in its translation, so I don't use S.??
> > > > > > > >          S.redirectTo(homePage)
>
> > > > > > > >        case xs =>
> > > > > > > >          S.error(xs)
> > > > > > > >          S.mapSnippet(S.currentSnippet.open_!, innerEdit)
> > > > > > > >      }
> > > > > > > >    }
>
> > > > > > > >    def innerEdit(t: NodeSeq) = bind("user", t,
> > > > > > > >                                "field" -> ((h: NodeSeq) =>
> > > > localForm
> > > > > > > > (h, theUser, true)),
> > > > > > > >                                "submit" ->
> > > > SHtml.submit(S.??("edit"),
> > > > > > > > testEdit _))
> > > > > > > >    innerEdit(xhtml)
> > > > > > > >  }
>
> > > > > > > >  /** Make a form with all the editable fields of an user, from
> > a
> > > > > > > > template */
> > > > > > > >  protected def localForm(xhtml: NodeSeq, user: User,
> > > > ignorePassword:
> > > > > > > > Boolean): NodeSeq = {
> > > > > > > >    signupFields
> > > > > > > >      .map(fi => getSingleton.getActualBaseField(user, fi))
> > //get
> > > > > > > > actual fields
> > > > > > > >      .filter(f => !ignorePassword || (f match { //remove the
> > > > password
> > > > > > > > field
> > > > > > > >        case f: MappedPassword[_] => false
> > > > > > > >        case _ => true
> > > > > > > >      }))
> > > > > > > >      .flatMap(f =>
> > > > > > > >          bind("field", xhtml,
> > > > > > > >            "name" -> Text(f.displayName),
> > > > > > > >            "form" -> f.toForm)
> > > > > > > >        )
> > > > > > > >  }
>
> > -------------------------------------------------------------------------------------------------
> > > > > > > > The template:
>
> > > > > > > > <lift:surround with="default" at="content">
> > > > > > > >    <lift:User.edit form="POST">
> > > > > > > >        <table>
> > > > > > > >            <tbody>
> > > > > > > >                <user:field>
> > > > > > > >                    <tr>
>
> ...
>
> read more ≫

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