The first of a series of coding vignettes in Seaside.
Context: a web app with a form containing multiple input fields. Instead of waiting to submit the form, I want the page to update another element every time an input is changed. In this example, a total field. Solution was used for a simple MoneyCounter application:
MoneyCounter>>renderContentOn: html html form id: 'f'; with: [ html table: [ html tableRow: [html tableData: [html text: 'pennies']; tableData: [html textInput id: 'pennies'; "on: #pennies of: self;" callback: [:value | self pennies: value]; onChange: (html updater id: 'total'; triggerFormElement: 'pennies'; callback: [ :r | self renderTotalOn: r]) ] ] etc. html tableRow: [html tableData: [html text: 'TOTAL'; space]; tableData: [html span id: 'total' ; with: self total]]]]
MoneyCounter>>renderTotalOn: html html render: self total
MoneyCounter>>pennies: value
pennies := value MoneyCounter>>total ^((pennies asInteger * 0.01) + etc. )
The real action demonstrated here is in onChange: . onChange will accept a Javascript function or an SUUpdater to automagically do the Javascript functioning. html updater returns just such an SUUpdater, and the two important things this updater does is a define a callback block of code – this block will be called everytime onChange is triggered – in this case, to renderTotalOn. Important, though, for this block to work correctly, is to also call triggerFormElement. This will trigger the callback block on the element itself, callback: [:value | self pennies: value], then also do the updater callback. Without the triggerFormElement, calling renderTotalOn will update the total with the “old” value of pennies, instead of what the user had currently entered.
In simple English, whenever the input field is changed, update the value that is bound to the field, then update the Total field.
For this to work appropriately, it’s also important to set element ids correctly. The updater also seems to require an id – and seemingly that id must be the same as the element that it is updating, but I’m not exactly clear on this yet.