I have tried several methods without luck, but found a solution now. I don't want to rewrite the Tapestry javascript code if I don't have to, but found a way by stopping propagation of the events.zone.update. I have a filter on a grid. The grid is big and when Tapestry calls $.append(content) to insert zone data the browser gets very laggy. By including the input value in the zone, then I can check on match with the current user input when zone is ready to update. The mixin accept multiple zones.
I tried http://jumpstart.doublenegative.com.au/jumpstart/examples/ajax/onevent, but I does not sync data and will display wrong result (om large zone updates). Debugging: STOP: stopPropagation UPDT: Let zone update be handled as default Test on currentInputVal vs inputValInZone STOP: tes !== t zone:destinationTableZone STOP: tes !== t zone:destinationCountZone STOP: test !== te zone:destinationTableZone STOP: test !== te zone:destinationCountZone STOP: test !== tes zone:destinationTableZone STOP: test !== tes zone:destinationCountZone UPDT: test === test zone:destinationTableZone ZONEUPDATE UPDT: test === test zone:destinationCountZone ZONEUPDATE STOP: testla !== testl zone:destinationTableZone STOP: testla !== testl zone:destinationCountZone STOP: testlab !== testla zone:destinationTableZone STOP: testlab !== testla zone:destinationCountZone STOP: testlab2 !== testlab zone:destinationTableZone STOP: testlab2 !== testlab zone:destinationCountZone UPDT: testlab2 === testlab2 zone:destinationTableZone ZONEUPDATE UPDT: testlab2 === testlab2 zone:destinationCountZone ZONEUPDATE The code: mixins\ZoneSync.java: public class ZoneSync { @Parameter(required = true, allowNull = false) Object[] zones; @Inject JavaScriptSupport javaScriptSupport; @InjectContainer ClientElement clientElement; @AfterRender void afterRender() { String zonesSelector = Arrays.stream(this.zones).map(zone -> "#" + ((Zone) zone).getClientId()).collect(Collectors.joining(",")); javaScriptSupport.require("mixins/zone-sync").invoke("syncWithInput").with("#" + clientElement.getClientId(), zonesSelector); } } Zone-sync.ts: export = class ZoneSync { /* <t:zone t:id="<zoneId>"> <!-- Add div.sync --> <div class="sync" hidden="">${<TextField.value>}</div> */ static syncWithInput(textFieldSelector: string, zonesSelector: string) { let textField = $(textFieldSelector); Dom.on(zonesSelector, Events.zone.update, function (this: ElementWrapper, event: EventWrapper) { let currentInputVal = textField.val(); let inputValInZone = $(`<div>${(event.memo.content)}</div>`).children(".sync").first().text(); if (currentInputVal !== inputValInZone) { event.nativeEvent.stopPropagation(); console.log(`STOP: ${currentInputVal} !== ${inputValInZone} zone:${this.element.id}`); } else { console.log(`UPDT: ${currentInputVal} === ${inputValInZone} zone:${this.element.id}`); } }); } } TML: <t:form t:id="nameFilterForm" id="nameFilterForm" async="true" autofocus="true" style="display:flex;align-items: center;"> <t:label for="nameFilterField">Name:</t:label> <t:textfield t:mixins="jacillacore/ZoneSync" zoneSync.zones="[destinationTableZone, destinationCountZone]" t:id="nameFilterField" oninput="$(this).closest('form').submit()" style="vertical-align: top" value="nameFilter" autocomplete="off" /> <t:zone t:id="destinationCountZone"> <div class="sync" hidden="">${nameFilter}</div> ${destinationBeans.size()}</t:zone> </t:form> <t:zone t:id="destinationTableZone"> <div class="sync" hidden="">${nameFilter}</div> <t:grid renderTableIfEmpty="true" style="width:auto" source="destinationBeans" rowClass="prop:rowClass" class="table table-hover table-bordered" t:row="destinationBean" model="model" rowsPerPage="1000" t:pagerPosition="top"> S-E -----Original Message----- From: Cezary Biernacki <cezary...@gmail.com> Sent: lørdag 8. juni 2019 00:09 To: Tapestry users <users@tapestry.apache.org> Subject: Re: How to let the last ajaxResponseRenderer win? Hi, A server-side solution will not solve the problem, as responses from the server can be re-ordered because of network transmission hick-ups. With Tapestry, you can the abort Ajax requests on client-side as well, it uses Jquery (or Prototype.js) under the hood. I would monkey-patch dom.ajaxRequest function (see t5-core-dom-jquery.js or t5-core-dom-prototype.js depending if your are using Jquery or Prototype), to track currently running AJAX requests and abort it if a new one is issued using Jquery's or XMLHttpRequest's abort methods. A more advanced solution would allow multiple requests and only abort ones that are conflicting with each other. Cezary On Fri, Jun 7, 2019 at 8:44 PM Dmitry Gusev <dmitry.gu...@gmail.com> wrote: > Hi, > > There’s no reliable way to do so as all requests arrive simultaneously > on the server side, so unless you do a distributed lock — which is not > a good idea usually — there’s no way to do so. > > One of ideas is: you could pass sequential number with every request, > put that number in a storage (like Redis) using compare and set, and > if request is older than the one already in storage — do nothing. > > Usually such requests are throttled on the client side, I.e.: > https://github.com/cowboy/jquery-throttle-debounce > > On Friday, June 7, 2019, Svein-Erik Løken <se.lo...@brav.com> wrote: > > > When typing "test" pretty fast into textfield id=nameFilter the > > result is wrong. I am typical getting "DEBUG nameFilter: te" (sometimes > > just "t"). > > The grid data corresponds to the nameFilter output. > > > > The output from getNamefilterDebug() is always: > > getNamefilterDebug: t > > getNamefilterDebug: te > > getNamefilterDebug: tes > > getNamefilterDebug: test > > > > > > > > <t:form t:id="nameFilterForm" id="nameFilterForm" async="true" > > autofocus="true" style="display:flex;align-items: center;"> > > <t:label for="nameFilter">Name:</t:label> > > <t:textfield t:id="nameFilter" > oninput="$(this).closest('form').submit()" > > style="vertical-align: top" value="nameFilter" autocomplete="off"/> > > <t:zone t:id="destinationCountZone">${destinationBeans.size()}</t: > > zone> > > </t:form> > > > > <t:zone t:id="destinationTableZone"> > > DEBUG nameFilter: ${namefilterDebug} > > > > <t:grid renderTableIfEmpty="true" style="width:auto" > > source="destinationBeans" rowClass="prop:rowClass" class="table > table-hover > > table-bordered" t:row="destinationBean" model="model" rowsPerPage="1000" > > t:pagerPosition="top"> > > > > > > void onSubmitFromNameFilterForm() { > > applyFilter(); > > ajaxResponseRenderer.addRender(destinationTableZone); > > } > > > > > > public String getNamefilterDebug() { > > System.err.format("getNamefilterDebug: %s%n",nameFilter); > > return nameFilter; > > } > > > > > > When using JavaScript/React I just call XMLHttpRequest.abort() for > > all ongoing XHR's. > > > > > > I cannot figure out how to do this in Tapestry 5.4.4. I was looking > > for AjaxResponseRenderer addRender(ClientBodyElement zone, > > abortPrevious); > > > > S-E > > > > > > > > > > -- > Dmitry Gusev > > AnjLab Team > http://anjlab.com >