Dynamic Web Development with Seaside

20.4.3Updating XHTML

The most important feature of AJAX is the ability to update parts of a page, without having the browser request and parse a whole new page from scratch. This is important since in most web applications only small parts of a page change with each user interaction.

If you look carefully at your todo list page in the browser, you’ll notice that the colour of your todo items doesn’t change when you mark them as completed. It would be nice if we could change the colour of a todo item depending on its state and give the user visual feedback. Let’s make the following change to our code:

ToDoListView>>renderContentOn: html
self renderHeadingOn: html.
html form: [
html unorderedList
id: (listId := html nextId); "<-- ensure you have this"
with: [ self renderItemsOn: html ].
html submitButton
text: 'Save'.
html submitButton
callback: [ self add ];
text: 'Add' ].
html render: editor
ToDoListView>>renderItem: anItem on: html
html listItem
class: 'done' if: anItem isDone;
class: 'overdue' if: anItem isOverdue;
with: [
html checkbox
onChange: (html scriptaculous updater "<-- added"
id: listId;
triggerForm: (html scriptaculous element up: 'form');
callback: [ :ajaxHtml | self renderItemsOn: ajaxHtml ]);
value: anItem done;
callback: [ :value | anItem done: value ].
html text: anItem title.
html space.
html anchor
callback: [ self edit: anItem ];
with: 'edit'.
html space.
html anchor
callback: [ self remove: anItem ];
with: 'remove' ]

We asked Seaside for a unique ID using html nextId. We store this ID in an instance-variable and assign it to the unordered list in renderContentOn: to be able to refer to it in renderItem:on: as a target of an AJAX update action.

In renderItem:on: we replaced the requestor method with an updater, which understands many of the same messages as a requestor, but can also update the page once the form’s callbacks have been processed. Since we still want the server to process the changes to the form, we keep the line that triggers the form. To allow the update to happen, we need to give the updater two new pieces of information.

First, we pass the ID of the DOM element that we want it to update. When the update happens, that whole section of your page will be removed, and replaced by some new content that you must specify.

Second, in order to specify the new content, we create a callback block which will be triggered to render. Notice that we pass a new renderer ajaxHtml to the callback block; the block uses this renderer to render the list of items. Also notice that the checkbox has two callbacks now: one responsible for the state of the checkbox, the other one responsible to update the HTML.

It is important that you use only the renderer passed as argument to the AJAX callback block. Do not to use the html canvas of the outer context. html is invalid at the time the AJAX callback is triggered since it already has been sent out to the web browser when the full page request was processed.

You may have a look at the classes PTAjax and its subclasses PTUpdater and PTRequest. You will notice that they have many common messages they understand.

If you play with the application you will see that the state of the checkboxes is submitted now. You can observe that the colors of the individual items change as you click the checkboxes, this is because the updater re-renders the listing with the changed items.

Copyright © 19 March 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.