Executing form callbacks within a block

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Executing form callbacks within a block

Esteban A. Maringolo
Hi all,

I have a situation where I want to execute _ALL_ the callbacks of the
inputs in the form within a particular block (basically, a DB
transaction).

html form: [
  html textInput on: #name of: self.
  html textInput on: #age of: self.
  html submitButton
]

I want to execute the three callbacks within something else, or at
least have the option to execute something before the first callback
executes and ensure something gets executed after the last one is
executed.

I know it involves fiddling somehow with
WACallbackProcessingActionContinuation, but it's not fully clear if I
could do this.

The hacky alternative would be to have a hidden field that does start
the tx and the submit / cancel commits or cancels it.

html form: [
  html hiddenInput callback: [self beginTransaction].
  html textInput on: #name of: self.
  html textInput on: #age of: self.
  html submitButton
    callback: [self commitTransaction];
    value: 'Submit'.
]

But in this case I'd have to keep the tx "outside" of the form, and
I'd like to wrap everything in a single block.

Is there a way to do this with Seaside?

Thanks!

Esteban A. Maringolo
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Karsten Kusche
Hi Esteban,

i think you’re using VisualWorks, so BufferedValueHolders may be an option here. In a normal VisualWorks ApplicationModel you’d define each input’s aspect with an additional trigger like so: "name | trigger“ or „age | trigger“. The UIBuilder would then create BufferedValueHolders around the ValueModels for name and age. The #trigger is another ValueHolder that you control with your submit/cancel buttons: trigger value: true for submit and trigger value: false for cancel.
All the trigger really does is submit the values to their actual ValueModels (on submit) or discard the changes on cancel. But in your case it would allow you to control the moment when the values are really submitted. 

ValueModels is something Seaside never really considered, there the getter/setter approach is preferred. But we use it in SeaBreeze pretty successfully. Especially because ValueHolders are used in VisualWorks UIs to communicate Changes back to the UI, which is super useful in Seaside, when you can have automatic Updates on the Website without a need to manually refresh the related elements.

If not with ValueModels i’d still solve your problem not on a Seaside level but rather on some other abstraction level. Whatever „self“ is in your example, maybe you should consider getting/setting the values form someone else and have this object take care of the transaction stuff upon submit.

Kind Regards
Karsten

— 

Georg Heeg eK
Wallstraße 22
06366 Köthen

Tel.: 03496/214328
FAX: 03496/214712
Amtsgericht Dortmund HRA 12812


Am 20. Mai 2021 um 03:19:14, Esteban Maringolo ([hidden email]) schrieb:

Hi all,

I have a situation where I want to execute _ALL_ the callbacks of the
inputs in the form within a particular block (basically, a DB
transaction).

html form: [
html textInput on: #name of: self.
html textInput on: #age of: self.
html submitButton
]

I want to execute the three callbacks within something else, or at
least have the option to execute something before the first callback
executes and ensure something gets executed after the last one is
executed.

I know it involves fiddling somehow with
WACallbackProcessingActionContinuation, but it's not fully clear if I
could do this.

The hacky alternative would be to have a hidden field that does start
the tx and the submit / cancel commits or cancels it.

html form: [
html hiddenInput callback: [self beginTransaction].
html textInput on: #name of: self.
html textInput on: #age of: self.
html submitButton
callback: [self commitTransaction];
value: 'Submit'.
]

But in this case I'd have to keep the tx "outside" of the form, and
I'd like to wrap everything in a single block.

Is there a way to do this with Seaside?

Thanks!

Esteban A. Maringolo
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Esteban A. Maringolo
Hi Karsten,

I'm not using VW in this case, I'm using Pharo.

I understand the use case of BufferedValueHolders, in Magritte the
MAMemento plays a similar role (but without using ValueModels), but
I'm not using either of these, and I'd favor using the MAMemento in
this particular case (I already have the descriptions in place).

My question was more specific about whether there were such "hooks" or
context for all the callbacks belonging to a form.

Thanks for your reply!

Esteban A. Maringolo

On Thu, May 20, 2021 at 2:38 AM Karsten Kusche <[hidden email]> wrote:

>
> Hi Esteban,
>
> i think you’re using VisualWorks, so BufferedValueHolders may be an option here. In a normal VisualWorks ApplicationModel you’d define each input’s aspect with an additional trigger like so: "name | trigger“ or „age | trigger“. The UIBuilder would then create BufferedValueHolders around the ValueModels for name and age. The #trigger is another ValueHolder that you control with your submit/cancel buttons: trigger value: true for submit and trigger value: false for cancel.
> All the trigger really does is submit the values to their actual ValueModels (on submit) or discard the changes on cancel. But in your case it would allow you to control the moment when the values are really submitted.
>
> ValueModels is something Seaside never really considered, there the getter/setter approach is preferred. But we use it in SeaBreeze pretty successfully. Especially because ValueHolders are used in VisualWorks UIs to communicate Changes back to the UI, which is super useful in Seaside, when you can have automatic Updates on the Website without a need to manually refresh the related elements.
>
> If not with ValueModels i’d still solve your problem not on a Seaside level but rather on some other abstraction level. Whatever „self“ is in your example, maybe you should consider getting/setting the values form someone else and have this object take care of the transaction stuff upon submit.
>
> Kind Regards
> Karsten
>
> —
>
> Georg Heeg eK
>
> Wallstraße 22
> 06366 Köthen
>
> Tel.: 03496/214328
> FAX: 03496/214712
> Amtsgericht Dortmund HRA 12812
>
>
>
> Am 20. Mai 2021 um 03:19:14, Esteban Maringolo ([hidden email]) schrieb:
>
> Hi all,
>
> I have a situation where I want to execute _ALL_ the callbacks of the
> inputs in the form within a particular block (basically, a DB
> transaction).
>
> html form: [
> html textInput on: #name of: self.
> html textInput on: #age of: self.
> html submitButton
> ]
>
> I want to execute the three callbacks within something else, or at
> least have the option to execute something before the first callback
> executes and ensure something gets executed after the last one is
> executed.
>
> I know it involves fiddling somehow with
> WACallbackProcessingActionContinuation, but it's not fully clear if I
> could do this.
>
> The hacky alternative would be to have a hidden field that does start
> the tx and the submit / cancel commits or cancels it.
>
> html form: [
> html hiddenInput callback: [self beginTransaction].
> html textInput on: #name of: self.
> html textInput on: #age of: self.
> html submitButton
> callback: [self commitTransaction];
> value: 'Submit'.
> ]
>
> But in this case I'd have to keep the tx "outside" of the form, and
> I'd like to wrap everything in a single block.
>
> Is there a way to do this with Seaside?
>
> Thanks!
>
> Esteban A. Maringolo
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Esteban A. Maringolo
In reply to this post by Esteban A. Maringolo
Well..

I'm not writing the values directly to the database, but I'm using
GLORP in between.
Glorp detects changes and at the end of a "unit of work" (kinda
transaction) it creates the corresponding statements to
write/update/delete rows in the database. But in order to do that it
has to know the object "state" before starting doing mutations on it.

So what I finally did was to have a hidden input as the first callback.

A super simplified version, without validations and whatnot is like this:

html form: [
  html hiddenInput callback: [self db beginUnitOrWork. self db
register: self model].
  html textInput on: #name of: self model.
  html submitButton callback: [self db commitUnitOfWork]
]

Regards!

Esteban A. Maringolo

On Wed, May 19, 2021 at 10:59 PM Jupiter Jones <[hidden email]> wrote:

>
> To be clearer… :)
>
> No callback on the submit button.
>
> html form callback: [
>         self beginTransaction.
>         “Update database from #name and #age fields”
>         self commitTransaction
> ]
>
> > On 20 May 2021, at 11:55 am, Jupiter Jones <[hidden email]> wrote:
> >
> > It’s been a while since I’ve done this, but if you have a callback on the form itself, which handles validation and if valid, starts a transaction, moves the data from the temporary variables used by the web form to the database, then commits.
> >
> > I’m guessing from the question that you may have bound your inputs directly to database objects that will revert their value when you beginTransaction?
> >
> >> On 20 May 2021, at 11:18 am, Esteban Maringolo <[hidden email]> wrote:
> >>
> >> Hi all,
> >>
> >> I have a situation where I want to execute _ALL_ the callbacks of the
> >> inputs in the form within a particular block (basically, a DB
> >> transaction).
> >>
> >> html form: [
> >> html textInput on: #name of: self.
> >> html textInput on: #age of: self.
> >> html submitButton
> >> ]
> >>
> >> I want to execute the three callbacks within something else, or at
> >> least have the option to execute something before the first callback
> >> executes and ensure something gets executed after the last one is
> >> executed.
> >>
> >> I know it involves fiddling somehow with
> >> WACallbackProcessingActionContinuation, but it's not fully clear if I
> >> could do this.
> >>
> >> The hacky alternative would be to have a hidden field that does start
> >> the tx and the submit / cancel commits or cancels it.
> >>
> >> html form: [
> >> html hiddenInput callback: [self beginTransaction].
> >> html textInput on: #name of: self.
> >> html textInput on: #age of: self.
> >> html submitButton
> >>   callback: [self commitTransaction];
> >>   value: 'Submit'.
> >> ]
> >>
> >> But in this case I'd have to keep the tx "outside" of the form, and
> >> I'd like to wrap everything in a single block.
> >>
> >> Is there a way to do this with Seaside?
> >>
> >> Thanks!
> >>
> >> Esteban A. Maringolo
> >> _______________________________________________
> >> seaside mailing list
> >> [hidden email]
> >> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Karsten Kusche
In reply to this post by Esteban A. Maringolo
Hi Esteban,



My question was more specific about whether there were such "hooks" or 
context for all the callbacks belonging to a form. 

I don’t see any such concept of „callbacks belonging to a form“ in Seaside. As far as the form is concerned, only a <form> is rendered. As far as the callbacks are concerned, a couple of Integers are computed and rendered. No connection whatsoever is made between the two.

The callback-registry only keeps counting up when new stuff is registered. Could be callbacks, could be something else. You never know for sure.

Kind Regards

Karsten


— 

Georg Heeg eK
Wallstraße 22
06366 Köthen

Tel.: 03496/214328
FAX: 03496/214712
Amtsgericht Dortmund HRA 12812


Am 20. Mai 2021 um 16:04:25, Esteban Maringolo ([hidden email]) schrieb:

Hi Karsten,

I'm not using VW in this case, I'm using Pharo.

I understand the use case of BufferedValueHolders, in Magritte the
MAMemento plays a similar role (but without using ValueModels), but
I'm not using either of these, and I'd favor using the MAMemento in
this particular case (I already have the descriptions in place).

My question was more specific about whether there were such "hooks" or
context for all the callbacks belonging to a form.

Thanks for your reply!

Esteban A. Maringolo

On Thu, May 20, 2021 at 2:38 AM Karsten Kusche <[hidden email]> wrote:
>
> Hi Esteban,
>
> i think you’re using VisualWorks, so BufferedValueHolders may be an option here. In a normal VisualWorks ApplicationModel you’d define each input’s aspect with an additional trigger like so: "name | trigger“ or „age | trigger“. The UIBuilder would then create BufferedValueHolders around the ValueModels for name and age. The #trigger is another ValueHolder that you control with your submit/cancel buttons: trigger value: true for submit and trigger value: false for cancel.
> All the trigger really does is submit the values to their actual ValueModels (on submit) or discard the changes on cancel. But in your case it would allow you to control the moment when the values are really submitted.
>
> ValueModels is something Seaside never really considered, there the getter/setter approach is preferred. But we use it in SeaBreeze pretty successfully. Especially because ValueHolders are used in VisualWorks UIs to communicate Changes back to the UI, which is super useful in Seaside, when you can have automatic Updates on the Website without a need to manually refresh the related elements.
>
> If not with ValueModels i’d still solve your problem not on a Seaside level but rather on some other abstraction level. Whatever „self“ is in your example, maybe you should consider getting/setting the values form someone else and have this object take care of the transaction stuff upon submit.
>
> Kind Regards
> Karsten
>
> —
>
> Georg Heeg eK
>
> Wallstraße 22
> 06366 Köthen
>
> Tel.: 03496/214328
> FAX: 03496/214712
> Amtsgericht Dortmund HRA 12812
>
>
>
> Am 20. Mai 2021 um 03:19:14, Esteban Maringolo ([hidden email]) schrieb:
>
> Hi all,
>
> I have a situation where I want to execute _ALL_ the callbacks of the
> inputs in the form within a particular block (basically, a DB
> transaction).
>
> html form: [
> html textInput on: #name of: self.
> html textInput on: #age of: self.
> html submitButton
> ]
>
> I want to execute the three callbacks within something else, or at
> least have the option to execute something before the first callback
> executes and ensure something gets executed after the last one is
> executed.
>
> I know it involves fiddling somehow with
> WACallbackProcessingActionContinuation, but it's not fully clear if I
> could do this.
>
> The hacky alternative would be to have a hidden field that does start
> the tx and the submit / cancel commits or cancels it.
>
> html form: [
> html hiddenInput callback: [self beginTransaction].
> html textInput on: #name of: self.
> html textInput on: #age of: self.
> html submitButton
> callback: [self commitTransaction];
> value: 'Submit'.
> ]
>
> But in this case I'd have to keep the tx "outside" of the form, and
> I'd like to wrap everything in a single block.
>
> Is there a way to do this with Seaside?
>
> Thanks!
>
> Esteban A. Maringolo
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

jtuchel
In reply to this post by Esteban A. Maringolo
Esteban,

not sure if I understand correctly, but I would like to point you to an
idea I got from a Form validation framework called mold
(https://github.com/grype/Seaside-Mold 
<https://github.com/grype/Seaside-Mold>). Your hidden input idea is
going to carry you quite far, but you can even make it a bit "safer" by
creating a special callback that has a higher priority than the other
action  callbacks.

Just subclass WAActionCallback and implement #priority to return a value
lower than 5 to make sure it is executed before the action callbacks
(but after the value callbacks).

This will be a bit safer than just relying on the order of the action
callbacks in your form (which might be enough already).

HTH

Joachim





Am 20.05.21 um 16:10 schrieb Esteban Maringolo:

> Well..
>
> I'm not writing the values directly to the database, but I'm using
> GLORP in between.
> Glorp detects changes and at the end of a "unit of work" (kinda
> transaction) it creates the corresponding statements to
> write/update/delete rows in the database. But in order to do that it
> has to know the object "state" before starting doing mutations on it.
>
> So what I finally did was to have a hidden input as the first callback.
>
> A super simplified version, without validations and whatnot is like this:
>
> html form: [
>    html hiddenInput callback: [self db beginUnitOrWork. self db
> register: self model].
>    html textInput on: #name of: self model.
>    html submitButton callback: [self db commitUnitOfWork]
> ]
>
> Regards!
>
> Esteban A. Maringolo
>
> On Wed, May 19, 2021 at 10:59 PM Jupiter Jones <[hidden email]> wrote:
>> To be clearer… :)
>>
>> No callback on the submit button.
>>
>> html form callback: [
>>          self beginTransaction.
>>          “Update database from #name and #age fields”
>>          self commitTransaction
>> ]
>>
>>> On 20 May 2021, at 11:55 am, Jupiter Jones <[hidden email]> wrote:
>>>
>>> It’s been a while since I’ve done this, but if you have a callback on the form itself, which handles validation and if valid, starts a transaction, moves the data from the temporary variables used by the web form to the database, then commits.
>>>
>>> I’m guessing from the question that you may have bound your inputs directly to database objects that will revert their value when you beginTransaction?
>>>
>>>> On 20 May 2021, at 11:18 am, Esteban Maringolo <[hidden email]> wrote:
>>>>
>>>> Hi all,
>>>>
>>>> I have a situation where I want to execute _ALL_ the callbacks of the
>>>> inputs in the form within a particular block (basically, a DB
>>>> transaction).
>>>>
>>>> html form: [
>>>> html textInput on: #name of: self.
>>>> html textInput on: #age of: self.
>>>> html submitButton
>>>> ]
>>>>
>>>> I want to execute the three callbacks within something else, or at
>>>> least have the option to execute something before the first callback
>>>> executes and ensure something gets executed after the last one is
>>>> executed.
>>>>
>>>> I know it involves fiddling somehow with
>>>> WACallbackProcessingActionContinuation, but it's not fully clear if I
>>>> could do this.
>>>>
>>>> The hacky alternative would be to have a hidden field that does start
>>>> the tx and the submit / cancel commits or cancels it.
>>>>
>>>> html form: [
>>>> html hiddenInput callback: [self beginTransaction].
>>>> html textInput on: #name of: self.
>>>> html textInput on: #age of: self.
>>>> html submitButton
>>>>    callback: [self commitTransaction];
>>>>    value: 'Submit'.
>>>> ]
>>>>
>>>> But in this case I'd have to keep the tx "outside" of the form, and
>>>> I'd like to wrap everything in a single block.
>>>>
>>>> Is there a way to do this with Seaside?
>>>>
>>>> Thanks!
>>>>
>>>> Esteban A. Maringolo
>>>> _______________________________________________
>>>> seaside mailing list
>>>> [hidden email]
>>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


--
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          mailto:[hidden email]
Fliederweg 1                         http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Esteban A. Maringolo
In reply to this post by Karsten Kusche
Yeap, that's what I knew. For good or bad everything is isolated.

But maybe there could be something.

For this very simple case, however, I solved it with a hidden input as
I mentioned in other reply.

Thanks again!

Esteban A. Maringolo

On Thu, May 20, 2021 at 11:11 AM Karsten Kusche <[hidden email]> wrote:

>
> Hi Esteban,
>
>
>
> My question was more specific about whether there were such "hooks" or
> context for all the callbacks belonging to a form.
>
> I don’t see any such concept of „callbacks belonging to a form“ in Seaside. As far as the form is concerned, only a <form> is rendered. As far as the callbacks are concerned, a couple of Integers are computed and rendered. No connection whatsoever is made between the two.
>
> The callback-registry only keeps counting up when new stuff is registered. Could be callbacks, could be something else. You never know for sure.
>
> Kind Regards
>
> Karsten
>
>
> —
>
> Georg Heeg eK
>
> Wallstraße 22
> 06366 Köthen
>
> Tel.: 03496/214328
> FAX: 03496/214712
> Amtsgericht Dortmund HRA 12812
>
>
>
> Am 20. Mai 2021 um 16:04:25, Esteban Maringolo ([hidden email]) schrieb:
>
> Hi Karsten,
>
> I'm not using VW in this case, I'm using Pharo.
>
> I understand the use case of BufferedValueHolders, in Magritte the
> MAMemento plays a similar role (but without using ValueModels), but
> I'm not using either of these, and I'd favor using the MAMemento in
> this particular case (I already have the descriptions in place).
>
> My question was more specific about whether there were such "hooks" or
> context for all the callbacks belonging to a form.
>
> Thanks for your reply!
>
> Esteban A. Maringolo
>
> On Thu, May 20, 2021 at 2:38 AM Karsten Kusche <[hidden email]> wrote:
> >
> > Hi Esteban,
> >
> > i think you’re using VisualWorks, so BufferedValueHolders may be an option here. In a normal VisualWorks ApplicationModel you’d define each input’s aspect with an additional trigger like so: "name | trigger“ or „age | trigger“. The UIBuilder would then create BufferedValueHolders around the ValueModels for name and age. The #trigger is another ValueHolder that you control with your submit/cancel buttons: trigger value: true for submit and trigger value: false for cancel.
> > All the trigger really does is submit the values to their actual ValueModels (on submit) or discard the changes on cancel. But in your case it would allow you to control the moment when the values are really submitted.
> >
> > ValueModels is something Seaside never really considered, there the getter/setter approach is preferred. But we use it in SeaBreeze pretty successfully. Especially because ValueHolders are used in VisualWorks UIs to communicate Changes back to the UI, which is super useful in Seaside, when you can have automatic Updates on the Website without a need to manually refresh the related elements.
> >
> > If not with ValueModels i’d still solve your problem not on a Seaside level but rather on some other abstraction level. Whatever „self“ is in your example, maybe you should consider getting/setting the values form someone else and have this object take care of the transaction stuff upon submit.
> >
> > Kind Regards
> > Karsten
> >
> > —
> >
> > Georg Heeg eK
> >
> > Wallstraße 22
> > 06366 Köthen
> >
> > Tel.: 03496/214328
> > FAX: 03496/214712
> > Amtsgericht Dortmund HRA 12812
> >
> >
> >
> > Am 20. Mai 2021 um 03:19:14, Esteban Maringolo ([hidden email]) schrieb:
> >
> > Hi all,
> >
> > I have a situation where I want to execute _ALL_ the callbacks of the
> > inputs in the form within a particular block (basically, a DB
> > transaction).
> >
> > html form: [
> > html textInput on: #name of: self.
> > html textInput on: #age of: self.
> > html submitButton
> > ]
> >
> > I want to execute the three callbacks within something else, or at
> > least have the option to execute something before the first callback
> > executes and ensure something gets executed after the last one is
> > executed.
> >
> > I know it involves fiddling somehow with
> > WACallbackProcessingActionContinuation, but it's not fully clear if I
> > could do this.
> >
> > The hacky alternative would be to have a hidden field that does start
> > the tx and the submit / cancel commits or cancels it.
> >
> > html form: [
> > html hiddenInput callback: [self beginTransaction].
> > html textInput on: #name of: self.
> > html textInput on: #age of: self.
> > html submitButton
> > callback: [self commitTransaction];
> > value: 'Submit'.
> > ]
> >
> > But in this case I'd have to keep the tx "outside" of the form, and
> > I'd like to wrap everything in a single block.
> >
> > Is there a way to do this with Seaside?
> >
> > Thanks!
> >
> > Esteban A. Maringolo
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Esteban A. Maringolo
In reply to this post by jtuchel
Hi Joachim,

Thanks for pointing that out, I forgot about Mold. It's not exactly
what I needed, but having a special kind of callback is something I
could certainly use. I did that for specific purposes but never for
changing the processing priority.

Thanks again!


Esteban A. Maringolo

On Thu, May 20, 2021 at 11:30 AM [hidden email]
<[hidden email]> wrote:

>
> Esteban,
>
> not sure if I understand correctly, but I would like to point you to an
> idea I got from a Form validation framework called mold
> (https://github.com/grype/Seaside-Mold
> <https://github.com/grype/Seaside-Mold>). Your hidden input idea is
> going to carry you quite far, but you can even make it a bit "safer" by
> creating a special callback that has a higher priority than the other
> action  callbacks.
>
> Just subclass WAActionCallback and implement #priority to return a value
> lower than 5 to make sure it is executed before the action callbacks
> (but after the value callbacks).
>
> This will be a bit safer than just relying on the order of the action
> callbacks in your form (which might be enough already).
>
> HTH
>
> Joachim
>
>
>
>
>
> Am 20.05.21 um 16:10 schrieb Esteban Maringolo:
> > Well..
> >
> > I'm not writing the values directly to the database, but I'm using
> > GLORP in between.
> > Glorp detects changes and at the end of a "unit of work" (kinda
> > transaction) it creates the corresponding statements to
> > write/update/delete rows in the database. But in order to do that it
> > has to know the object "state" before starting doing mutations on it.
> >
> > So what I finally did was to have a hidden input as the first callback.
> >
> > A super simplified version, without validations and whatnot is like this:
> >
> > html form: [
> >    html hiddenInput callback: [self db beginUnitOrWork. self db
> > register: self model].
> >    html textInput on: #name of: self model.
> >    html submitButton callback: [self db commitUnitOfWork]
> > ]
> >
> > Regards!
> >
> > Esteban A. Maringolo
> >
> > On Wed, May 19, 2021 at 10:59 PM Jupiter Jones <[hidden email]> wrote:
> >> To be clearer… :)
> >>
> >> No callback on the submit button.
> >>
> >> html form callback: [
> >>          self beginTransaction.
> >>          “Update database from #name and #age fields”
> >>          self commitTransaction
> >> ]
> >>
> >>> On 20 May 2021, at 11:55 am, Jupiter Jones <[hidden email]> wrote:
> >>>
> >>> It’s been a while since I’ve done this, but if you have a callback on the form itself, which handles validation and if valid, starts a transaction, moves the data from the temporary variables used by the web form to the database, then commits.
> >>>
> >>> I’m guessing from the question that you may have bound your inputs directly to database objects that will revert their value when you beginTransaction?
> >>>
> >>>> On 20 May 2021, at 11:18 am, Esteban Maringolo <[hidden email]> wrote:
> >>>>
> >>>> Hi all,
> >>>>
> >>>> I have a situation where I want to execute _ALL_ the callbacks of the
> >>>> inputs in the form within a particular block (basically, a DB
> >>>> transaction).
> >>>>
> >>>> html form: [
> >>>> html textInput on: #name of: self.
> >>>> html textInput on: #age of: self.
> >>>> html submitButton
> >>>> ]
> >>>>
> >>>> I want to execute the three callbacks within something else, or at
> >>>> least have the option to execute something before the first callback
> >>>> executes and ensure something gets executed after the last one is
> >>>> executed.
> >>>>
> >>>> I know it involves fiddling somehow with
> >>>> WACallbackProcessingActionContinuation, but it's not fully clear if I
> >>>> could do this.
> >>>>
> >>>> The hacky alternative would be to have a hidden field that does start
> >>>> the tx and the submit / cancel commits or cancels it.
> >>>>
> >>>> html form: [
> >>>> html hiddenInput callback: [self beginTransaction].
> >>>> html textInput on: #name of: self.
> >>>> html textInput on: #age of: self.
> >>>> html submitButton
> >>>>    callback: [self commitTransaction];
> >>>>    value: 'Submit'.
> >>>> ]
> >>>>
> >>>> But in this case I'd have to keep the tx "outside" of the form, and
> >>>> I'd like to wrap everything in a single block.
> >>>>
> >>>> Is there a way to do this with Seaside?
> >>>>
> >>>> Thanks!
> >>>>
> >>>> Esteban A. Maringolo
> >>>> _______________________________________________
> >>>> seaside mailing list
> >>>> [hidden email]
> >>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
> --
> -----------------------------------------------------------------------
> Objektfabrik Joachim Tuchel          mailto:[hidden email]
> Fliederweg 1                         http://www.objektfabrik.de
> D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
> Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1
>
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Johan Brichau-2
Hi Esteban,

Seaside’s defined callback priorities guarantee that the submit button callback is executed after the value callbacks on the input form’s fields.

Although you can fiddle with creating additional WAValueCallback subclasses, I would not recommend it.
Instead, I would collect the values in a ‘value collector’ object, like what Karsten proposes. Roughly:

        collector := MyValueCollector new.
        html form:[
    html textInput callback: [ :e | collector setA: e];
                html textInput callback: [ :e | collector setB: e];
                html submitButton callback: [ collector save ] ]

When the first value is added to the collector, you execute the code that needs to be executed first (i.e. ’start transaction’). The collector knows because it gathers all the values.
The submit button callback then executes the final action (’save’).

Is that not the easiest solution to what you want to achieve?

cheers
Johan


> On 20 May 2021, at 17:29, Esteban Maringolo <[hidden email]> wrote:
>
> Hi Joachim,
>
> Thanks for pointing that out, I forgot about Mold. It's not exactly
> what I needed, but having a special kind of callback is something I
> could certainly use. I did that for specific purposes but never for
> changing the processing priority.
>
> Thanks again!
>
>
> Esteban A. Maringolo
>
> On Thu, May 20, 2021 at 11:30 AM [hidden email]
> <[hidden email]> wrote:
>>
>> Esteban,
>>
>> not sure if I understand correctly, but I would like to point you to an
>> idea I got from a Form validation framework called mold
>> (https://github.com/grype/Seaside-Mold
>> <https://github.com/grype/Seaside-Mold>). Your hidden input idea is
>> going to carry you quite far, but you can even make it a bit "safer" by
>> creating a special callback that has a higher priority than the other
>> action  callbacks.
>>
>> Just subclass WAActionCallback and implement #priority to return a value
>> lower than 5 to make sure it is executed before the action callbacks
>> (but after the value callbacks).
>>
>> This will be a bit safer than just relying on the order of the action
>> callbacks in your form (which might be enough already).
>>
>> HTH
>>
>> Joachim
>>
>>
>>
>>
>>
>> Am 20.05.21 um 16:10 schrieb Esteban Maringolo:
>>> Well..
>>>
>>> I'm not writing the values directly to the database, but I'm using
>>> GLORP in between.
>>> Glorp detects changes and at the end of a "unit of work" (kinda
>>> transaction) it creates the corresponding statements to
>>> write/update/delete rows in the database. But in order to do that it
>>> has to know the object "state" before starting doing mutations on it.
>>>
>>> So what I finally did was to have a hidden input as the first callback.
>>>
>>> A super simplified version, without validations and whatnot is like this:
>>>
>>> html form: [
>>>   html hiddenInput callback: [self db beginUnitOrWork. self db
>>> register: self model].
>>>   html textInput on: #name of: self model.
>>>   html submitButton callback: [self db commitUnitOfWork]
>>> ]
>>>
>>> Regards!
>>>
>>> Esteban A. Maringolo
>>>
>>> On Wed, May 19, 2021 at 10:59 PM Jupiter Jones <[hidden email]> wrote:
>>>> To be clearer… :)
>>>>
>>>> No callback on the submit button.
>>>>
>>>> html form callback: [
>>>>         self beginTransaction.
>>>>         “Update database from #name and #age fields”
>>>>         self commitTransaction
>>>> ]
>>>>
>>>>> On 20 May 2021, at 11:55 am, Jupiter Jones <[hidden email]> wrote:
>>>>>
>>>>> It’s been a while since I’ve done this, but if you have a callback on the form itself, which handles validation and if valid, starts a transaction, moves the data from the temporary variables used by the web form to the database, then commits.
>>>>>
>>>>> I’m guessing from the question that you may have bound your inputs directly to database objects that will revert their value when you beginTransaction?
>>>>>
>>>>>> On 20 May 2021, at 11:18 am, Esteban Maringolo <[hidden email]> wrote:
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> I have a situation where I want to execute _ALL_ the callbacks of the
>>>>>> inputs in the form within a particular block (basically, a DB
>>>>>> transaction).
>>>>>>
>>>>>> html form: [
>>>>>> html textInput on: #name of: self.
>>>>>> html textInput on: #age of: self.
>>>>>> html submitButton
>>>>>> ]
>>>>>>
>>>>>> I want to execute the three callbacks within something else, or at
>>>>>> least have the option to execute something before the first callback
>>>>>> executes and ensure something gets executed after the last one is
>>>>>> executed.
>>>>>>
>>>>>> I know it involves fiddling somehow with
>>>>>> WACallbackProcessingActionContinuation, but it's not fully clear if I
>>>>>> could do this.
>>>>>>
>>>>>> The hacky alternative would be to have a hidden field that does start
>>>>>> the tx and the submit / cancel commits or cancels it.
>>>>>>
>>>>>> html form: [
>>>>>> html hiddenInput callback: [self beginTransaction].
>>>>>> html textInput on: #name of: self.
>>>>>> html textInput on: #age of: self.
>>>>>> html submitButton
>>>>>>   callback: [self commitTransaction];
>>>>>>   value: 'Submit'.
>>>>>> ]
>>>>>>
>>>>>> But in this case I'd have to keep the tx "outside" of the form, and
>>>>>> I'd like to wrap everything in a single block.
>>>>>>
>>>>>> Is there a way to do this with Seaside?
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> Esteban A. Maringolo
>>>>>> _______________________________________________
>>>>>> seaside mailing list
>>>>>> [hidden email]
>>>>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>> _______________________________________________
>>> seaside mailing list
>>> [hidden email]
>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>>
>> --
>> -----------------------------------------------------------------------
>> Objektfabrik Joachim Tuchel          mailto:[hidden email]
>> Fliederweg 1                         http://www.objektfabrik.de
>> D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
>> Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1
>>
>>
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Executing form callbacks within a block

Esteban A. Maringolo
Hi Johan,

I never thought of using my own "value collector" class for this, I
either used Magritte's MAMemento or assigned values directly to the
object, but this option is so simple that I don't know why I never
thought about it before, it solves some use cases with so much
simplicity without having to rely on separate instVars!

Thanks!


ps: I'd like, however, that somehow the form values could be available
somewhere, as if the form data was a first class object, very much
like the collector, that you can get maybe asking for it to the
request context. But I'm now goint to make it, so I'll KISS. :-)


Esteban A. Maringolo

On Thu, May 20, 2021 at 4:07 PM Johan Brichau <[hidden email]> wrote:

>
> Hi Esteban,
>
> Seaside’s defined callback priorities guarantee that the submit button callback is executed after the value callbacks on the input form’s fields.
>
> Although you can fiddle with creating additional WAValueCallback subclasses, I would not recommend it.
> Instead, I would collect the values in a ‘value collector’ object, like what Karsten proposes. Roughly:
>
>         collector := MyValueCollector new.
>         html form:[
>                 html textInput callback: [ :e | collector setA: e];
>                 html textInput callback: [ :e | collector setB: e];
>                 html submitButton callback: [ collector save ] ]
>
> When the first value is added to the collector, you execute the code that needs to be executed first (i.e. ’start transaction’). The collector knows because it gathers all the values.
> The submit button callback then executes the final action (’save’).
>
> Is that not the easiest solution to what you want to achieve?
>
> cheers
> Johan
>
>
> > On 20 May 2021, at 17:29, Esteban Maringolo <[hidden email]> wrote:
> >
> > Hi Joachim,
> >
> > Thanks for pointing that out, I forgot about Mold. It's not exactly
> > what I needed, but having a special kind of callback is something I
> > could certainly use. I did that for specific purposes but never for
> > changing the processing priority.
> >
> > Thanks again!
> >
> >
> > Esteban A. Maringolo
> >
> > On Thu, May 20, 2021 at 11:30 AM [hidden email]
> > <[hidden email]> wrote:
> >>
> >> Esteban,
> >>
> >> not sure if I understand correctly, but I would like to point you to an
> >> idea I got from a Form validation framework called mold
> >> (https://github.com/grype/Seaside-Mold
> >> <https://github.com/grype/Seaside-Mold>). Your hidden input idea is
> >> going to carry you quite far, but you can even make it a bit "safer" by
> >> creating a special callback that has a higher priority than the other
> >> action  callbacks.
> >>
> >> Just subclass WAActionCallback and implement #priority to return a value
> >> lower than 5 to make sure it is executed before the action callbacks
> >> (but after the value callbacks).
> >>
> >> This will be a bit safer than just relying on the order of the action
> >> callbacks in your form (which might be enough already).
> >>
> >> HTH
> >>
> >> Joachim
> >>
> >>
> >>
> >>
> >>
> >> Am 20.05.21 um 16:10 schrieb Esteban Maringolo:
> >>> Well..
> >>>
> >>> I'm not writing the values directly to the database, but I'm using
> >>> GLORP in between.
> >>> Glorp detects changes and at the end of a "unit of work" (kinda
> >>> transaction) it creates the corresponding statements to
> >>> write/update/delete rows in the database. But in order to do that it
> >>> has to know the object "state" before starting doing mutations on it.
> >>>
> >>> So what I finally did was to have a hidden input as the first callback.
> >>>
> >>> A super simplified version, without validations and whatnot is like this:
> >>>
> >>> html form: [
> >>>   html hiddenInput callback: [self db beginUnitOrWork. self db
> >>> register: self model].
> >>>   html textInput on: #name of: self model.
> >>>   html submitButton callback: [self db commitUnitOfWork]
> >>> ]
> >>>
> >>> Regards!
> >>>
> >>> Esteban A. Maringolo
> >>>
> >>> On Wed, May 19, 2021 at 10:59 PM Jupiter Jones <[hidden email]> wrote:
> >>>> To be clearer… :)
> >>>>
> >>>> No callback on the submit button.
> >>>>
> >>>> html form callback: [
> >>>>         self beginTransaction.
> >>>>         “Update database from #name and #age fields”
> >>>>         self commitTransaction
> >>>> ]
> >>>>
> >>>>> On 20 May 2021, at 11:55 am, Jupiter Jones <[hidden email]> wrote:
> >>>>>
> >>>>> It’s been a while since I’ve done this, but if you have a callback on the form itself, which handles validation and if valid, starts a transaction, moves the data from the temporary variables used by the web form to the database, then commits.
> >>>>>
> >>>>> I’m guessing from the question that you may have bound your inputs directly to database objects that will revert their value when you beginTransaction?
> >>>>>
> >>>>>> On 20 May 2021, at 11:18 am, Esteban Maringolo <[hidden email]> wrote:
> >>>>>>
> >>>>>> Hi all,
> >>>>>>
> >>>>>> I have a situation where I want to execute _ALL_ the callbacks of the
> >>>>>> inputs in the form within a particular block (basically, a DB
> >>>>>> transaction).
> >>>>>>
> >>>>>> html form: [
> >>>>>> html textInput on: #name of: self.
> >>>>>> html textInput on: #age of: self.
> >>>>>> html submitButton
> >>>>>> ]
> >>>>>>
> >>>>>> I want to execute the three callbacks within something else, or at
> >>>>>> least have the option to execute something before the first callback
> >>>>>> executes and ensure something gets executed after the last one is
> >>>>>> executed.
> >>>>>>
> >>>>>> I know it involves fiddling somehow with
> >>>>>> WACallbackProcessingActionContinuation, but it's not fully clear if I
> >>>>>> could do this.
> >>>>>>
> >>>>>> The hacky alternative would be to have a hidden field that does start
> >>>>>> the tx and the submit / cancel commits or cancels it.
> >>>>>>
> >>>>>> html form: [
> >>>>>> html hiddenInput callback: [self beginTransaction].
> >>>>>> html textInput on: #name of: self.
> >>>>>> html textInput on: #age of: self.
> >>>>>> html submitButton
> >>>>>>   callback: [self commitTransaction];
> >>>>>>   value: 'Submit'.
> >>>>>> ]
> >>>>>>
> >>>>>> But in this case I'd have to keep the tx "outside" of the form, and
> >>>>>> I'd like to wrap everything in a single block.
> >>>>>>
> >>>>>> Is there a way to do this with Seaside?
> >>>>>>
> >>>>>> Thanks!
> >>>>>>
> >>>>>> Esteban A. Maringolo
> >>>>>> _______________________________________________
> >>>>>> seaside mailing list
> >>>>>> [hidden email]
> >>>>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >>> _______________________________________________
> >>> seaside mailing list
> >>> [hidden email]
> >>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >>
> >>
> >> --
> >> -----------------------------------------------------------------------
> >> Objektfabrik Joachim Tuchel          mailto:[hidden email]
> >> Fliederweg 1                         http://www.objektfabrik.de
> >> D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
> >> Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1
> >>
> >>
> >> _______________________________________________
> >> seaside mailing list
> >> [hidden email]
> >> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside