Tapestry
  1. Tapestry
  2. TAPESTRY-1673

Why does submitType="cancel" kill its listener?

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Won't Fix
    • Affects Version/s: 4.1.2
    • Fix Version/s: 4.1.6
    • Component/s: Core Components
    • Labels:
      None
    • Environment:
      Tap 4.1.2, Firefox 2.0.0.5 or IE 7 on Win XP SP2, Safari 2.0.4 or Firefox 2.0.0.5 on OS X 10.4.10, served by Tomcat in JBoss 4.2.1.

      Description

      Is there a reason why submitType kills its component's listener? For example, whereas this listener works...

      <input jwcid="@Submit" type="submit" value="Cancel" action="listener:doCancel">

      ... the listener in this one is ignored...

      <input jwcid="@Submit" type="submit" value="Cancel" action="listener:doCancel" submitType="cancel"/>

      ...and the listener has to be specified on the Form instead...

      <form jwcid="@Form" cancel="listener:doCancel">

      Why is this so? What if I want more than one button of type cancel, each one with its own listener, and possibly its own parameters? I think submitType="refresh" behaves this way, too.

      Here's a working example:

      package sandpit;

      import org.apache.tapestry.html.BasePage;

      public abstract class CancelPage extends BasePage {
      public abstract void setMessage1(String value);
      public abstract void setMessage2(String value);

      public void doComponentListener()

      { setMessage1("doComponentListener() invoked."); }

      public void doFormListener()

      { setMessage2("doFormListener() invoked."); }

      }

      <html jwcid="@Shell" title="">
      <body jwcid="@Body">
      <h2>Demonstration of how submitType="cancel" kills the component's listener</h2>

      <form jwcid="@Form">
      <fieldset>
      <legend>This form does NOT specify a cancel listener</legend>

      Whereas this listener works...<br/>
      <input jwcid="@Submit" type="submit" value="Submit" action="listener:doComponentListener"/> GOOD<br/>
      <code><input jwcid="@Submit" type="submit" value="Submit" action="listener:doComponentListener"/></code><br/><br/>

      ... the listener in this one is ignored, which is bad...<br/>
      <input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel" action="listener:doComponentListener"/> BAD<br/>
      <code><input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel" action="listener:doComponentListener"/></code><br/><br/>
      </fieldset>
      </form>

      <form jwcid="@Form" cancel="listener:doFormListener">
      <fieldset>
      <legend>This form specifies cancel="listener:doFormListener"</legend>

      Whereas this listener works...<br/>
      <input jwcid="@Submit" type="submit" value="Submit" action="listener:doComponentListener"/> GOOD<br/>
      <code><input jwcid="@Submit" type="submit" value="Submit" action="listener:doComponentListener"/></code><br/><br/>

      ... the listener in this one is ignored, and the form's listener takes over, which is questionable...<br/>
      <input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel" action="listener:doComponentListener" /> QUESTIONABLE<br/>
      <code><input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel" action="listener:doComponentListener"/></code><br/><br/>

      ...but in this case the form's listener works... <br/>
      <input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel"/> GOOD<br/>
      <code><input jwcid="@Submit" type="submit" value="Cancel" submitType="cancel"/></code><br/><br/>
      </fieldset>
      </form>

      Message1: <span style="color: red;"><span jwcid="@Insert" value="ognl:message1">Message</span></span><br/>
      Message2: <span style="color: blue;"><span jwcid="@Insert" value="ognl:message2">Message</span></span>
      </body>
      </html>

        Activity

        Hide
        Andreas Andreou added a comment -

        i'm not sure why the cancel submit doesn't call its own listener first - it indeed only calls the forms cancel listener

        And I need that behavior as well, so ...

        Show
        Andreas Andreou added a comment - i'm not sure why the cancel submit doesn't call its own listener first - it indeed only calls the forms cancel listener And I need that behavior as well, so ...
        Hide
        Jesse Kuhnert added a comment -

        I'm not entirely sure what can be done about this issue......If you look at the documentation on the Form success/cancel/refresh combined with the knowledge that it's impossible to know that any particular button has been clicked unless you do rewind the whole form - it makes things "tricky".

        The cancel logic is currently happening because FormSupportImpl reads the submit mode parameter and doesn't even rewind the form. I'm not sure how we can bypass this functionality without breaking existing applications...I'm not really sure.

        The refresh listeners should have their listeners called correctly - if this isn't happening for you please let me know.

        You can of course very easily just use a normal listener and have it perform whatever cancel logic you need still though right?

        At the very least the various submit buttons/links should probably throw a runtime exception indicating that you can't have a submit type of "cancel" and a listener/action bound as it will never be called.

        thoughts?

        Show
        Jesse Kuhnert added a comment - I'm not entirely sure what can be done about this issue......If you look at the documentation on the Form success/cancel/refresh combined with the knowledge that it's impossible to know that any particular button has been clicked unless you do rewind the whole form - it makes things "tricky". The cancel logic is currently happening because FormSupportImpl reads the submit mode parameter and doesn't even rewind the form. I'm not sure how we can bypass this functionality without breaking existing applications...I'm not really sure. The refresh listeners should have their listeners called correctly - if this isn't happening for you please let me know. You can of course very easily just use a normal listener and have it perform whatever cancel logic you need still though right? At the very least the various submit buttons/links should probably throw a runtime exception indicating that you can't have a submit type of "cancel" and a listener/action bound as it will never be called. thoughts?
        Hide
        Andreas Andreou added a comment -

        you're right - the contract for the cancel listener has always been that it doesn't rewind the form - as i now recall

        i'll double check the refresh listener and close this.

        Show
        Andreas Andreou added a comment - you're right - the contract for the cancel listener has always been that it doesn't rewind the form - as i now recall i'll double check the refresh listener and close this.
        Hide
        Andreas Andreou added a comment -

        Looked at what happens with refresh listener of @Submit...
        It is called only when async=true - it is skipped on normal submits!

        The javascript for the first case (async) is:
        tapestry.form.refresh("msg", "cc",

        {"async":true,"json":false,"url":"Page,ms.sdirect"}

        );
        and for the normal case it is:
        tapestry.form.refresh('msg','cc')

        Need to dig some more to see why

        Show
        Andreas Andreou added a comment - Looked at what happens with refresh listener of @Submit... It is called only when async=true - it is skipped on normal submits! The javascript for the first case (async) is: tapestry.form.refresh("msg", "cc", {"async":true,"json":false,"url":"Page,ms.sdirect"} ); and for the normal case it is: tapestry.form.refresh('msg','cc') Need to dig some more to see why
        Hide
        Alejandro Scandroli added a comment -

        I don't know if this is the same issue or a new one, but in 4.1.5 a Submit component with submitType="cancel" and no action listener doesn't call the cancel listener of the enclosing Form component.
        e.g:
        <form jwcid="@Form" cancel="listener:doCancel">
        <input jwcid="@Submit" value="Cancel" submitType="cancel"/>
        </form

        This was working on 4.1.3

        Show
        Alejandro Scandroli added a comment - I don't know if this is the same issue or a new one, but in 4.1.5 a Submit component with submitType="cancel" and no action listener doesn't call the cancel listener of the enclosing Form component. e.g: <form jwcid="@Form" cancel="listener:doCancel"> <input jwcid="@Submit" value="Cancel" submitType="cancel"/> </form This was working on 4.1.3
        Hide
        Andreas Andreou added a comment -

        Alejandro, no! What you're seeing is TAPESTRY-2225

        as for "submitType=cancel killing its listener", it happens because there's no
        rewind taking place in that case.

        Show
        Andreas Andreou added a comment - Alejandro, no! What you're seeing is TAPESTRY-2225 as for "submitType=cancel killing its listener", it happens because there's no rewind taking place in that case.

          People

          • Assignee:
            Andreas Andreou
            Reporter:
            Geoff Callender
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development