You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Peter Ertl (JIRA)" <ji...@apache.org> on 2007/12/08 13:42:43 UTC

[jira] Issue Comment Edited: (WICKET-1213) enable subclassing of AjaxRequestTarget

    [ https://issues.apache.org/jira/browse/WICKET-1213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12549696 ] 

pete edited comment on WICKET-1213 at 12/8/07 4:41 AM:
-------------------------------------------------------------

here's an example of how this could be used -- you might get an better idea of what I want to achieve with this patch...

this is some code inside my template page:


  @Override
  public AjaxRequestTarget newAjaxRequestTarget()
  {
    final AjaxRequestTarget target = super.newAjaxRequestTarget();

    target.addListener(new AjaxRequestTarget.IListener()
    {
      @SuppressWarnings({"RawUseOfParameterizedType"})
      public void onBeforeRespond(final Map map, final AjaxRequestTarget target)
      {
        // always render the feedback component that belongs to this template
        // no need to include it in all pages that use this template
        target.addComponent(feedbackPanel);
      }

      @SuppressWarnings({"RawUseOfParameterizedType"})
      public void onAfterRespond(final Map map, final AjaxRequestTarget.IJavascriptResponse response)
      {
        //
        // set the focus on the first form component that has errors
        // this is very convenient for the user as he doesn't have to click on the erroneous field first
        // 
        // this has to be rendered in onAfterRespond to be sure the dom component for setting focus on has
        // already been rendered in the dom structure of the browser
        //
        final FormComponent focus = (FormComponent) visitChildren(FormComponent.class, new IVisitor()
        {
          public Object component(final Component component)
          {
            final FormComponent formComponent = (FormComponent) component;

            if (formComponent.hasErrorMessage() && formComponent.getOutputMarkupId())
              return formComponent;

            return CONTINUE_TRAVERSAL;
          }
        });
        if (focus != null)
          target.focusComponent(focus);
      }
    });
    return target;
  }


another possible example (using common functionality specific to your application this time)

  @Override
  public AjaxRequestTarget newAjaxRequestTarget()
  {
    return new CustomAjaxRequestTarget(); // extends AjaxRequestTarget
  }


so inside your pages you could for example do this:


  public void onClick(final AjaxRequestTarget target)
  {
    final CustomAjaxRequestTarget customTarget = (CustomAjaxRequestTarget)target;
    
    // change some setting on the page
    // ..
    
    // let the user take notice of the change (the heavily-used effect from Ruby on Rails we probably all know)
    customTarget.applyYellowFadeEffect(component);

    // make it even more obvious (some freaky javascript :-)
    customTarget.letScreenShakeUpAndDown();

    // even half-blind people should see that (another crazy js)
    customTarget.zoomInAndOutAgain(component);
  }

this way you could provide some common ajax  functionality to your application which is easy to use and implementation details are perfectly hidden



      was (Author: pete):
    here's an example of how this could be used -- you might get an better idea of what I want to achieve with this patch...

this is some code inside my template page:


  @Override
  public AjaxRequestTarget newAjaxRequestTarget()
  {
    final AjaxRequestTarget target = super.newAjaxRequestTarget();

    target.addListener(new AjaxRequestTarget.IListener()
    {
      @SuppressWarnings({"RawUseOfParameterizedType"})
      public void onBeforeRespond(final Map map, final AjaxRequestTarget target)
      {
        // always render the feedback component that belongs to this template
        // no need to include it in all pages that use this template
        target.addComponent(feedbackPanel);
      }

      @SuppressWarnings({"RawUseOfParameterizedType"})
      public void onAfterRespond(final Map map, final AjaxRequestTarget.IJavascriptResponse response)
      {
        //
        // set the focus on the first form component that has errors
        // this is very convenient for the user as he doesn't have to click on the erroneous field first
        // 
        // this has to be rendered in onAfterRespond to be sure the dom component for setting focus on has
        // already been rendered in the dom structure of the browser
        //
        final FormComponent focus = (FormComponent) visitChildren(FormComponent.class, new IVisitor()
        {
          public Object component(final Component component)
          {
            final FormComponent formComponent = (FormComponent) component;

            if (formComponent.hasErrorMessage() && formComponent.getOutputMarkupId())
              return formComponent;

            return CONTINUE_TRAVERSAL;
          }
        });
        if (focus != null)
          target.focusComponent(focus);
      }
    });
    return target;
  }


another possible example (using common functionality specific to your application this time)

  @Override
  public AjaxRequestTarget newAjaxRequestTarget()
  {
    return new CustomAjaxRequestTarget();
  }


so inside your pages you could for example do this:


  public void onClick(final AjaxRequestTarget target)
  {
    final CustomAjaxRequestTarget customTarget = (CustomAjaxRequestTarget)target;
    
    // change some setting on the page
    // ..
    
    // let the user take notice of the change (the heavily-used effect from Ruby on Rails we probably all know)
    customTarget.applyYellowFadeEffect(component);

    // make it even more obvious (some freaky javascript :-)
    customTarget.letScreenShakeUpAndDown();

    // even half-blind people should see that (another crazy js)
    customTarget.zoomInAndOutAgain(component);
  }

this way you could provide some common ajax  functionality to your application which is easy to use and implementation details are perfectly hidden


  
> enable subclassing of AjaxRequestTarget
> ---------------------------------------
>
>                 Key: WICKET-1213
>                 URL: https://issues.apache.org/jira/browse/WICKET-1213
>             Project: Wicket
>          Issue Type: Wish
>          Components: wicket
>    Affects Versions: 1.3.0-rc1
>            Reporter: Peter Ertl
>             Fix For: 1.4.0-alpha
>
>         Attachments: AjaxRequestTarget_with_subclassing.patch
>
>
> In my wicket programming life I always had some trouble with the ajax part when wanting stuff like this:
> - "Always update a common feedback panel from my template page"
>    --> add 'target.addComponent(feedbackPanel)' just _everywhere_ (very cumbersome and not elegant at all)
> - add a listener using AjaxRequestTarget#addListener
>   --> not quite possible without subclassing the request cycle (which is *yuk* if you ask me) to catch the short moment in between AjaxRequestTarget is instantiated and IRequestTarget#onRespond() is called
> - automatically set focus on the first form component with errors
>    --> add bulky code into all onError() to check for the proper component and call AjaxRequestTarget#setFocus
> - add some common function like AjaxRequestTarget#yellowFadeEffect(FormComponent)
>   --> have some utility method and call it like this: AjaxUtil.yellowFade(target) -- not nice as functionality like this should really belong to the ajax target which represents the ajax request / response.
> I found that all these issues can be solved very elegantly if you could just catch the moment where AjaxRequestTarget is instantiated.
> I attached a very little patch (!) which enables you to
> - subclass
> - add listeners to
> the AjaxRequestTarget
> In AbstractDefaultAjaxBehavior:281
>     public final void onRequest()
>     {
>         AjaxRequestTarget target = new AjaxRequestTarget(getComponent().getPage()); // *******
>         RequestCycle.get().setRequestTarget(target);
>         respond(target)
>     }
> is changed to
>     public final void onRequest()
>     {
>         AjaxRequestTarget target = getComponent().getPage().newAjaxRequestTarget(); // *******
>         RequestCycle.get().setRequestTarget(target);
>         respond(target);
>     }
> org.apache.wicket.Page will have an additional method:
>   public AjaxRequestTarget newAjaxRequestTarget()
>   {
>     return new AjaxRequestTarget(this);
>   }
> }
> so by overriding newAjaxRequestTarget in your page you could customize or subclass the ajax response very easily
> also, this will not break current code but is just an enhancement you will not notice unless you need it.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.