13.2Hotel Reservation: Task vs. Component
To compare when to use a task or a component, let’s build a minimal hotel reservation application using a task and a component with children. Using a task, it is easy to reuse components and build a flow. Here is a small application that illustrates how to do this. We want to ask the user to specify starting and ending reservation dates. We will define a new subclass of WATask
with two instance variables startDate
and endDate
of the selected period.
WATask subclass: #HotelTask
instanceVariableNames: 'startDate endDate'
classVariableNames: ''
poolDictionaries: ''
category: 'Calendars'
We define a method go
that will first create a calendar with selectable dates after today, then create a second calendar with selectable days after the one selected during the first interaction, and finally we will display the dates selected as shown in Figure 93.
HotelTask>>go
startDate := self call: (WAMiniCalendar new
canSelectBlock: [ :date | date > Date today ]).
endDate := self call: (WAMiniCalendar new
canSelectBlock: [ :date | startDate isNil or: [ startDate < date ] ]).
self inform: 'from ' , startDate asString , ' to ' ,
endDate asString , ' ' , (endDate - startDate) days asString ,
' days'
Note that you could add a confirmation step and loop until the user is OK with his reservation.
Now this solution is not satisfying because the user cannot see both calendars while making his selection. Since we can’t render components in our task, it’s not easy to remedy the situation. We could use the message addMessage: aString
to add a message to a component but this is still not good enough. This example demonstrates that tasks are about flow and not about presentation.
HotelTask>>go
startDate := self call: (WAMiniCalendar new
canSelectBlock: [ :date | date > Date today ];
addMessage: 'Select your starting date';
yourself).
endDate := self call: (WAMiniCalendar new
canSelectBlock: [ :date | startDate isNil or: [ startDate < date ] ];
addMessage: 'Select your leaving date';
yourself).
self inform: (endDate - startDate) days asString , ' days: from ' ,
startDate asString , ' to ' , endDate asString , ' '