I have created a component to hide all the gubbins that I mentioned earlier. All you need to do is create a more beautiful progress bar (my css skills aren't great). I have created a simple page which adds 3 progressRunnableLinks on a page. Each fires a task that takes 10 seconds, updating it's percentage complete as it goes.
1. Download the code from here http://dl.dropbox.com/u/63354/tapestry-progress.zip 2. run "mvn jetty:run" 3. Go to http://localhost:8080/tapestry/progress Cheers, Lance. Interesting bits of code: AppModule.java ---------------------- public ProgressRunnableManager buildProgressRunnableManager() { return new ProgressRunnableManagerImpl(20); } Progress.tml ------------------ <t:progressRunnableLink zoneId="zone1" linkText="start 1" progressRunnable="progressRunnable" pollDelayMillis="500" /> <t:progressRunnableLink zoneId="zone2" linkText="start 2" progressRunnable="progressRunnable" pollDelayMillis="500" /> <t:progressRunnableLink zoneId="zone3" linkText="start 3" progressRunnable="progressRunnable" pollDelayMillis="500" /> Progress.java (page class) -------------------- public class Progress { public ProgressRunnable getProgressRunnable() { return new AbstractProgressRunnable() { public void run() { for (int i = 1; i <= 10; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { } setProgressPercentage(i * 10); } } }; } } ProgressRunnableLink.java (component) ---------------------------------------------------------- @Import (library="zonemanager.js") public class ProgressRunnableLink { @Inject private ProgressRunnableManager manager; @Inject private AjaxResponseRenderer ajaxRenderer; @Inject private ComponentResources resources; @Inject private JavaScriptSupport jsSupport; @Parameter private Integer pollDelayMillis; @Parameter(defaultPrefix="literal", required=true) @Property private String linkText; @Parameter(defaultPrefix="literal", required=true) @Property private String zoneId; @Parameter(allowNull=false) private ProgressRunnable progressRunnable; @Property private Double progressPercentage; @Property private Exception exception; @InjectComponent private Zone progressZone; @OnEvent("startRunnable") Block startTask() { String taskId = manager.submit(progressRunnable); progressPercentage = 0D; doPoll(taskId); return progressZone.getBody(); } @OnEvent("updateProgress") Block updateProgress(String taskId) { try { progressPercentage = manager.getProgressPercentage(taskId); if (progressPercentage < 100D) { doPoll(taskId); } } catch (Exception e) { exception = e; } return progressZone.getBody(); } void doPoll(String taskId) { Link link = resources.createEventLink("updateProgress", taskId); final String url = link.toAbsoluteURI(); ajaxRenderer.addCallback(new JavaScriptCallback() { public void run(JavaScriptSupport jsSupport) { if (pollDelayMillis == null) { jsSupport.addScript("Tapestry.activateZone('%s', '%s');", zoneId, url); } else { jsSupport.addScript("setTimeout(\"Tapestry.activateZone('%s', '%s');\", %s);", zoneId, url, pollDelayMillis); } } }); } } On 3 January 2012 10:34, Lance Java <lance.j...@googlemail.com> wrote: > There are a couple of approaches to do this, since tapestry does not > support ajax push (aka reverse ajax) out-of-the box, a simple solution > would be to have the client poll the server for the current percentage > complete. > > In order to display a progress bar to the client, you must do the actual > work for the task on a separate thread to the Ajax request thread. It is > probably best to have a singleton ExecutorService (using > java.util.concurrent.Executors.newFixedThreadPool(threadCount) or similar) > > The Ajax request thread should: > 1. Create a runnable and give it a unique taskId > 2. Put the runnable in a serverside map keyed on taskId (map could be a > singleton or perhaps stored in each user's session) > > 3. Call executorService.submit(myRunnable) > 4. Use the AjaxResponseRenderer to fire the "updateProgressBar" event > passing the taskId in the context > 5. Return the progress bar zone's getBody() with a percentageComplete of 0 > > Your runnable would be something like > > public class MyWorker implements Runnable { > private int taskId; > private ConcurrentMap workers; > private AtomicInteger percentComplete = new AtomicInteger(0); > public MyWorker(ConcurrentMap workers, String taskId) { > this.workers = workers; > this.taskId = taskId; > } > public int getPercentComplete() { > return percentComplete.get(); > } > public void run() { > try { > doSomeWork(); > percentComplete.set(10); > doSomeMoreWork(); > percentComplete.set(50); > doEvenMoreWork(); > percentComplete.set(100); > } finally { > workers.remove(taskId); > } > } > } > > > In your serverside event handler [onUpdateProgressBar(String taskId)] > lookup the runnable in the map and call getPercentComplete() then return > the updated progress zone's getBody(). If the percentageComplete() is less > than 100, use the AjaxResponseRenderer to fire the "updateProgressBar" > event again. > > @see > http://tawus.wordpress.com/2011/10/01/tapestry-5-3-new-features-part-2/for > AjaxResponseRenderer usage > > Cheers, > Lance. > > > On Monday, 26 December 2011, angelochen <angelochen...@yahoo.com.hk> > wrote: > > Hi, > > > > would like to have some ideas about how to implement following: > > > > I have a t:grid, every row has a link, when click, it will do a process > > which might take a while, once done, it will either disable the link or > > re-display the link depending on the result. I'd like that, when clicked, > > the link is replaced with a progress bar in place, until it is done. any > > hints? Thanks, > > > > Angelo > > > > -- > > View this message in context: > http://tapestry.1045711.n5.nabble.com/T5-progress-bar-in-a-grid-tp5101565p5101565.html > > Sent from the Tapestry - User mailing list archive at Nabble.com. > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > > For additional commands, e-mail: users-h...@tapestry.apache.org > > > > >