10 Steps to Mastering The Art of Seaside ======================================== Seaside is an industrial strength framework for developing sophisticated Web applications in Smalltalk. Seaside provides a layered set of abstractions over HTTP and XHTML that let you build highly interactive Web applications quickly, reusably and maintainably. The goal of this session is to interactively build a small Web application together with the audience. Beginners will quickly gasp the key principles of the framework, so that afterwards they are able to write new applications and learn about the framework on their own. There will be plenty of room to ask questions and to demo advanced techniques you always wanted to learn about. 1. Different by Design - start-up image - install model 2. Components - WAComponent subclass: #ToDoListView instanceVariableNames: 'editor' classVariableNames: '' poolDictionaries: '' category: 'ToDo-View' - ToDoListView class>>initialize self registerAsApplication: 'todo' - show in browser: halos, browser 3. Rendering - ToDoListView>>renderContentOn: html - nothing to see so far 4. Canvas - ToDoListView>>model ^ ToDoList default - ToDoListView>>renderContentOn: html html render: self model title - display in browser 5. Brushes - ToDoListView>>renderContentOn: html html div class: 'title'; with: self model title. html div class: 'items'; with: [ self model items do: [ :each | self renderItem: each on: html ] ] - ToDoListView>>renderItem: anItem on: html html div class: 'item'; with: [ html render: anItem title ] - show generated output in rendering mode - edit stylesheet - ToDoListView>>style ^ '.title { font-size: 20px; font-weight: bold; margin-bottom: 10px; }' 6. Callbacks - ToDoListView>>renderItem: anItem on: html html div class: 'item'; with: [ html anchor callback: [ self edit: anItem ]; with: anItem title. html render: ' - '. html render: anItem due ] - ToDoListView>>edit: anItem self inform: anItem title - show rendered code 7. Forms - ToDoListView>>renderContentOn: html html div class: 'title'; with: self model title. html form: [ html div class: 'items'; with: [ self model items do: [ :each | self renderItem: each on: html ] ]. html submitButton text: 'Save' ] - ToDoListView>>renderItem: anItem on: html html div class: 'item'; with: [ html checkbox value: anItem done; callback: [ :value | anItem done: value ]. html render: anItem title. html space. html anchor callback: [ self edit: anItem ]; with: 'edit' ] 8. Call - WAComponent subclass: #ToDoItemView instanceVariableNames: 'model' classVariableNames: '' poolDictionaries: '' category: 'ToDo-View' - ToDoItemView>>model ^ model - ToDoItemView>>model: aModel model := aModel - ToDoListView>>edit: anItem self call: (ToDoItemView new model: anItem) - ToDoItemView>>renderContentOn: html html heading with: 'Edit'. html form: [ html text: 'Title:'; break. html textInput value: self model title; callback: [ :value | self model title: value ]. html break. html text: 'Due:'; break. html dateInput value: self model due; callback: [ :value | self model due: value ] ] 9. Answer - ToDoItemView>>renderContentOn: html html heading with: 'Edit'. html form: [ html text: 'Title:'; break. html textInput value: self model title; callback: [ :value | self model title: value ]. html break. html text: 'Due:'; break. html dateInput value: self model due; callback: [ :value | self model due: value ]. html break. html submitButton callback: [ self answer: self model ]; text: 'Save'. html submitButton callback: [ self answer: nil ]; text: 'Cancel' ] - ToDoItemView>>edit: anItem | result | result := self call: (ToDoItemView new model: anItem copy). result ifNotNil: [ self model items replaceAll: anItem with: result ] 10. Children - add i-var 'editor' - ToDoListView>>children ^ Array with: editor - ToDoListView>>renderContentOn: html html div class: 'title'; with: self model title. html form: [ html div class: 'items'; with: [ self model items do: [ :each | self renderItem: each on: html ] ]. html submitButton text: 'Save'. html submitButton callback: [ self add ]; text: 'Add New' ]. html render: editor - ToDoListView>>add editor := ToDoItemView new model: ToDoItem new. editor onAnswer: [ :value | value ifNotNil: [ self model add: value ]. editor := nil ] - play with halos turned on