You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Ilya Obshadko <il...@gmail.com> on 2009/11/17 20:03:27 UTC

simulate form submission events without Submit component

I have a task that looks quite simple, but still have a problem
accomplishing it.

Suppose you have a form with Select control, and onChange event on that
control should generate form submission event.

I've created a simple mixin for that.

public class SubmitOnChange {

    @Environmental

    private RenderSupport renderSupport;



    @Environmental

    private FormSupport formSupport;



    @InjectContainer

    private AbstractField container;



    @Inject

    private ComponentResources resources;



    @Parameter(required=true,allowNull=false,defaultPrefix="literal")

    private String submitEvent;



    @Parameter(required=false,allowNull=true,defaultPrefix="prop")

    private Object[] submitContext;



    public void afterRender () {

        final String formId = formSupport.getClientId ();

        final Link link = resources.createEventLink ( submitEvent,
submitContext );

        renderSupport.addInit ( "submitOnChange",

                new JSONArray ( formId, container.getClientId (),
link.toAbsoluteURI () ) );

    }


}

And accompanying JS:

Tapestry.Initializer.submitOnChange = function(formId, elementId, eventUrl)
{

    $(elementId).observe ("change", function(event) {

        $(formId).action = eventUrl;

        if ( $(elementId).value ) $(formId).submit ();

    });

};


Now, there is a problem. onChange event really submits the form, but the
event is fired on Select component instead of Form component and form values
are obviously lost during submission. If we comment out 3rd line in JS part,
it works correctly (because default form action is not altered), but this
way I lose an ability to control submission events names and I can intercept
events only by component names.

My goal is to simulate 'real' submit behavior. I believe it must be simple,
but I'm stuck. Any ideas?

-- 
Ilya Obshadko

Re: simulate form submission events without Submit component

Posted by Toby Hobson <to...@googlemail.com>.
I do something similar ... in fact I have created a mixin which I call
AjaxDelegate ... it basically wires up elements so that a client side event
on one component invokes a click event on a hidden submit button

Toby

2009/11/18 Thiago H. de Paula Figueiredo <th...@gmail.com>

> Em Wed, 18 Nov 2009 11:22:03 -0200, Ilya Obshadko <il...@gmail.com>
> escreveu:
>
>  ... anybody?
>>
>
> I would add a non-visible submit button (not the Submit component, an
> ordinary <input type="submit">) and then invoke submit.click(). That's what
> worked with AJAX submissions for me.
>
> --
> Thiago H. de Paula Figueiredo
> Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,
> and instructor
> Owner, software architect and developer, Ars Machina Tecnologia da
> Informação Ltda.
> http://www.arsmachina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: simulate form submission events without Submit component

Posted by Ilya Obshadko <il...@gmail.com>.
On Thu, Nov 19, 2009 at 1:10 AM, Thiago H. de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> Em Wed, 18 Nov 2009 20:00:22 -0200, Ilya Obshadko <il...@gmail.com>
> escreveu:
>
>
>  Finally, I've managed to create generic-purpose mixin that can trigger
>> form submit on any type of event and on any element within t:form component.
>> It works using standard Tapestry mechanisms (similarly to original Submit
>> component), supports multiple submit triggers within single form
>> (analogous to multiple submit buttons).
>>
>
> Please post it here. :)
>
>
Okay.

Mixin source:

@IncludeJavaScriptLibrary("submitonevent.js")

public class SubmitOnEvent {

    @Environmental

    private RenderSupport renderSupport;



    @Environmental

    private FormSupport formSupport;



    @InjectContainer

    private ClientElement container;



    @Inject

    private ComponentResources resources;



    @Inject

    private Request request;



    /**

     * Component event that triggers form submission; must be the name of
REAL JavaScript

     * event (click, change, blur etc.)

     */

    @Parameter(required=true,allowNull=false,defaultPrefix="literal")

    private String monitorEvent;



    /**

     * Tapestry submit event name that will be simulated during form
submission

     */

    @Parameter(required=true,allowNull=false,defaultPrefix="literal")

    private String submitEvent;



    /**

     * ID of the field that MUST have a value before form submission.

     * If field is empty, event is not triggered.

     */

    @Parameter(required=false,allowNull=false,defaultPrefix="literal")

    private String requiredField;



    /**

     * Form submit context

     */

    @Parameter(required=false,allowNull=false,defaultPrefix="prop")

    private Object[] submitContext;


    private static class ProcessFakeSubmission
implementsComponentAction<SubmitOnEvent> {

        private static final long serialVersionUID = -2205200857980521346L;

        private String fakeSubmitName;


        public ProcessFakeSubmission ( String fakeSubmitName ) {

            this.fakeSubmitName = fakeSubmitName;

        }


        public void execute ( SubmitOnEvent component ) {

            component.processFakeSubmission ( fakeSubmitName );

        }

    }



    public void afterRender () {

        final String formId = formSupport.getClientId ();

        formSupport.store ( this, new ProcessFakeSubmission ( "submit_" +
container.getClientId () ) );

        renderSupport.addInit ( "submitOnChange",

                new JSONArray ( monitorEvent, formId, container.getClientId
(), requiredField ) );

    }



    private void processFakeSubmission ( String elementName ) {

        String value = request.getParameter ( elementName );


        if ( value == null )

            return;


        Runnable sendNotification = new Runnable () {

            public void run () {

                resources.triggerEvent ( submitEvent, submitContext, null );

            }

        };


        formSupport.defer ( sendNotification );

    }


}

and JavaScript:

Tapestry.Initializer.submitOnChange = function(eventName, formId, elementId,
requiredField) {

    $(elementId).observe (eventName, function(event) {

        if ( ( requiredField && $(requiredField).value ) || ! requiredField
) {

            var hiddenSubmit = document.createElement("input");

            hiddenSubmit.type = "submit";

            hiddenSubmit.name = "submit_" + elementId;

            hiddenSubmit.style.visibility = "hidden";

            hiddenSubmit.style.display = "none";

            $(formId).appendChild(hiddenSubmit);

            hiddenSubmit.click();

        }

    });

};

The idea behind 'requiredField' parameter is simple: if parameter is
specified, this field must be filled in before triggering submit
event. Probably it's better to leave that up to Tapestry built-in
client-side validation, but I don't use it in my project (it's very
intrusive and its visual features doesn't fit the website design).

Enjoy!

-- 
Ilya Obshadko

Re: simulate form submission events without Submit component

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
Em Wed, 18 Nov 2009 20:00:22 -0200, Ilya Obshadko  
<il...@gmail.com> escreveu:

> Finally, I've managed to create generic-purpose mixin that can trigger  
> form submit on any type of event and on any element within t:form  
> component. It works using standard Tapestry mechanisms (similarly to  
> original Submit
> component), supports multiple submit triggers within single form  
> (analogous to multiple submit buttons).

Please post it here. :)

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, software architect and developer, Ars Machina Tecnologia da  
Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: simulate form submission events without Submit component

Posted by Ilya Obshadko <il...@gmail.com>.
Finally, I've managed to create generic-purpose mixin that can trigger form
submit on any type of event and on any element within t:form component. It
works using standard Tapestry mechanisms (similarly to original Submit
component), supports multiple submit triggers within single form (analogous
to multiple submit buttons).

If someone is interested in source code, let me know.

On Wed, Nov 18, 2009 at 9:29 PM, Ilya Obshadko <il...@gmail.com>wrote:

> On Wed, Nov 18, 2009 at 5:59 PM, Thiago H. de Paula Figueiredo <
> thiagohp@gmail.com> wrote:
>
>> Em Wed, 18 Nov 2009 11:22:03 -0200, Ilya Obshadko <
>> ilya.obshadko@gmail.com> escreveu:
>>
>>  ... anybody?
>>>
>>
>>
> Thanks! I thought about something similar, but I was hoping that it's
> possible without such kind of workaround.
>


-- 
Ilya Obshadko

Re: simulate form submission events without Submit component

Posted by Ilya Obshadko <il...@gmail.com>.
On Wed, Nov 18, 2009 at 5:59 PM, Thiago H. de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> Em Wed, 18 Nov 2009 11:22:03 -0200, Ilya Obshadko <il...@gmail.com>
> escreveu:
>
>  ... anybody?
>>
>
>
Thanks! I thought about something similar, but I was hoping that it's
possible without such kind of workaround.

-- 
Ilya Obshadko

Re: simulate form submission events without Submit component

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
Em Wed, 18 Nov 2009 11:22:03 -0200, Ilya Obshadko  
<il...@gmail.com> escreveu:

> ... anybody?

I would add a non-visible submit button (not the Submit component, an  
ordinary <input type="submit">) and then invoke submit.click(). That's  
what worked with AJAX submissions for me.

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, software architect and developer, Ars Machina Tecnologia da  
Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: simulate form submission events without Submit component

Posted by Ilya Obshadko <il...@gmail.com>.
... anybody?

On Tue, Nov 17, 2009 at 10:03 PM, Ilya Obshadko <il...@gmail.com>wrote:

> I have a task that looks quite simple, but still have a problem
> accomplishing it.
>
> Suppose you have a form with Select control, and onChange event on that
> control should generate form submission event.
>
> I've created a simple mixin for that.
>
> public class SubmitOnChange {
>
>     @Environmental
>
>     private RenderSupport renderSupport;
>
>
>
>     @Environmental
>
>     private FormSupport formSupport;
>
>
>
>     @InjectContainer
>
>     private AbstractField container;
>
>
>
>     @Inject
>
>     private ComponentResources resources;
>
>
>
>     @Parameter(required=true,allowNull=false,defaultPrefix="literal")
>
>     private String submitEvent;
>
>
>
>     @Parameter(required=false,allowNull=true,defaultPrefix="prop")
>
>     private Object[] submitContext;
>
>
>
>     public void afterRender () {
>
>         final String formId = formSupport.getClientId ();
>
>         final Link link = resources.createEventLink ( submitEvent,
> submitContext );
>
>         renderSupport.addInit ( "submitOnChange",
>
>                 new JSONArray ( formId, container.getClientId (),
> link.toAbsoluteURI () ) );
>
>     }
>
>
> }
>
> And accompanying JS:
>
> Tapestry.Initializer.submitOnChange = function(formId, elementId,
> eventUrl) {
>
>     $(elementId).observe ("change", function(event) {
>
>         $(formId).action = eventUrl;
>
>         if ( $(elementId).value ) $(formId).submit ();
>
>     });
>
> };
>
>
> Now, there is a problem. onChange event really submits the form, but the
> event is fired on Select component instead of Form component and form values
> are obviously lost during submission. If we comment out 3rd line in JS part,
> it works correctly (because default form action is not altered), but this
> way I lose an ability to control submission events names and I can intercept
> events only by component names.
>
> My goal is to simulate 'real' submit behavior. I believe it must be simple,
> but I'm stuck. Any ideas?
>
> --
> Ilya Obshadko
>
>
>


-- 
Ilya Obshadko