Nice solution Ben 😊 We found that we couldn’t visual style a submit input button to give feedback that the request was being processed so instead created a mixin that when the submit button was clicked, it was converted into a link that could then be styled with a spinner and visually disabled. It is a very hacky solution so happy to see alternative solutions especially with a submit input button.
DisableAfterSubmit.java import org.apache.tapestry5.ClientElement; import org.apache.tapestry5.annotations.Environmental; import org.apache.tapestry5.annotations.InjectContainer; import org.apache.tapestry5.annotations.MixinAfter; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.services.javascript.JavaScriptSupport; @MixinAfter public class DisableAfterSubmit { @InjectContainer private ClientElement element; @Environmental private JavaScriptSupport javaScriptSupport; void afterRender() { final JSONObject spec = new JSONObject(); spec.put("elementId", element.getClientId()); javaScriptSupport.require("pqc/mixins/DisableAfterSubmit").invoke("initialize").with(spec); } } DisableAfterSubmit.js (function() { define(["jquery"], function($j) { var initialize = function(spec) { $j('#' + spec.elementId).on('click', spec, afterClick); }; var afterClick = function(event) { // AJAX submit hack: to allow a spinner to be positioned by changing from an input[type=submit] to an anchor element // (as Tapestry form submissions via AJAX do not work now except through an input[type=submit]) var originalElement = $j('#' + event.data.elementId); var attrs = {'href':'#'}; var valueAttr; var idAttr = 'hack'; $j.each(originalElement[0].attributes, function(index, attr) { if (attr.nodeName === 'type') { // No need to add type=submit so continue return; } if (attr.nodeName === 'value') { valueAttr = attr.nodeValue; return; } if (attr.nodeName === 'id') { attrs[attr.nodeName] = attr.nodeValue + idAttr; return; } attrs[attr.nodeName] = attr.nodeValue; }); originalElement.hide(); originalElement.after(function () { return $j('<a/>', attrs).append(valueAttr); }); $j('#' + event.data.elementId + idAttr).addClass('disabled spinner').attr({'role':'alert', 'aria-busy':'true'}).focus(); }; return { initialize : initialize }; }); }).call(this); Cheers, Niran PS: I’m sorry if you receive this email twice as I used different email domain for subscribing to this list and I didn’t see that initial email come through. I have now subscribed using this email address.. From: Ben Weidig <b...@netzgut.net> Date: Sunday, 26 February 2023 at 14:22 To: Tapestry users <users@tapestry.apache.org> Subject: Re: Preventing double click eventlink and form submit Hi Nathan, Maybe I misunderstood your goal, but I would solve it with a module configured by CSS classes or data attributes instead of dedicated components. Something along the line of this (untested) CoffeeScript I improvised: define ['jquery', 't5/core/events'], ($, events) -> EVENT = 'click.request-in-progress' register = -> $('.show-request-in-progress').off(EVENT).on EVENT, -> $el = $(this) $el.addClass('request-in-progress') relatedZone = $el.data('target-zone') elEvent = "#{t5events.zone.wilUpdate}.##{$el.id}" zone.on elEvent, -> zone.off(elEvent) trigger.removeClass('request-in-progress') return true $ -> register() $(document).on events.zone.didUpdate, register See https://urldefense.com/v3/__https://gist.github.com/benweidig/2f2fdb32c74cbd57764b1f7dabbe7079__;!!NknhfzgzgQ!yowXeuZLQZ1AaayarMGyXEXL1HzNLMBuDQXODpgTaFvtxz2t3os3D2bD6FeSb24bEnUMv9tTOwG6dX3IZPu215m5$<https://urldefense.com/v3/__https:/gist.github.com/benweidig/2f2fdb32c74cbd57764b1f7dabbe7079__;!!NknhfzgzgQ!yowXeuZLQZ1AaayarMGyXEXL1HzNLMBuDQXODpgTaFvtxz2t3os3D2bD6FeSb24bEnUMv9tTOwG6dX3IZPu215m5$> for a nicely formatted version. This way, you wouldn't need an additional zone and just need to listen to the content zone to be updated. Only the ".show-request-in-progress" and "data-target-zone" must be set accordingly. Actually, the CSS classes isn't needed and the relevant elements could be targeted via the data attribute. Cheers Ben On Fri, Feb 24, 2023 at 2:11 PM Nathan Quirynen <nat...@pensionarchitects.be> wrote: > Hi, > > I am looking for a solution to prevent multiple clicks on event links or > form submits in our Tapestry application and in the meanwhile if > possible giving the user visual feedback while the request is being > processed. > We use ajax (async="true") on both our eventlinks and form components, > but there are no javascript events to hook into right before the request > is fired and when the request response is handled. But after some > research I found I can use the zone parameter instead of the async > parameter and then make use of the t5:zone:refresh and > t5:zone:did-update events to do exactly that. > So I came up with following javascript module which can be used for both > form submit buttons and eventlinks: > > var init = function(triggerClientId, zoneClientId) { > > var trigger = $('#' + triggerClientId); > var zone = $('#' + zoneClientId); > > var event_request = 't5:zone:refresh' + '.' + > triggerClientId; > > zone.on(event_request, function(e) { > > // disable trigger + add css class > trigger.css('pointer-events', 'none'); > trigger.addClass('request-in-progress'); > > var event_response = 't5:zone:did-update' + '.' + > triggerClientId; > zone.on(event_response, function() { > > // remove response event handler > zone.off(event_response); > > // reenable trigger + remove css class > trigger.css('pointer-events', 'auto'); > trigger.removeClass('request-in-progress'); > > }); > }); > > } > > I would make new components AjaxForm/AjaxEventLink to wrap the original > ones and implement everything there. > This seems to work as I hoped it would be, but then a zone element is > added for every EventLink/Form which seems a bit like overkill, but I > don't see another way at the moment. > I was wondering if others have tried to do something like I am, or if > there's any better way of achieving what I am trying here? Or anything > that I am missing could be wrong with my implementation? > > > Nathan > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > > Confidentiality note: This e-mail may contain confidential information from Clarivate. If you are not the intended recipient, be aware that any disclosure, copying, distribution or use of the contents of this e-mail is strictly prohibited. If you have received this e-mail in error, please delete this e-mail and notify the sender immediately.