Getting user input
So far we have avoided the issue of getting user input by simply providing a link to generate the next sequence. What we really should do is to permit the user to specify the length of the sequence. We do this by creating a form with an entry box for the user to enter the length of the sequence desired.
Modify the page template in app/controllers/views/fibonacci-generate-main.wtf as below:
[woof::pure::form { input {-label "Count to generate" -name numfibos -type text -required 1} buttons {{Generate -type submit -primary true} {Reset -type reset}} } -layout aligned] <hr> % my variable seq <p> The first [llength $seq] numbers in the Fibonacci sequence are shown below:</p> %( set index 0 set table {} foreach number $seq { lappend table [list [incr index] $number] } %) [woof::pure::table $table -heading {Sequence Number} -stripes 1]
The only significant change made is that we have added a form
element at the top to allow the user to enter the desired length of
the generated sequence. We have named this field
as numfibos
. When
the Generate button is clicked, the
form will be submitted to the same URL resulting in
the generate
method being called.
We now have to modify the generate method in
the fibonacci_controller.tcl file
accordingly. It now needs to handle the original request as well as
the requests posted through the Generate
button. Moreover, we will also add some simple validation to
demonstrate redirection and use of the flash
object.
method generate {} { # Generate the next number in the sequence. The sequence generated # so far is stored in the session. # Declare a member variable sequence to hold the Fibonacci sequence. # All member variables are automatically available for use in # the view templates. my variable seq # If the user has specified the length of the desired sequence, # use it, else use what we have in the session storage, else # initialize to the first two elements in sequence. if {![params exists numfibos num_fibos]} { # User has not specified length to generate if {[session exists num_fibos num_fibos]} { incr num_fibos; # One more than last time if {$num_fibos > 50} { set num_fibos 50 } } else { # Not in session storage either (first call) set num_fibos 2 } } if {(![string is integer -strict $num_fibos]) || $num_fibos > 50 || $num_fibos < 1} { flash set error_message "The length of the requested sequence must be an integer between 1 and 50." my redirect -action showerror return } if {$num_fibos == 1} { set seq {0} } else { set seq {0 1} for {set i 2} {$i < $num_fibos} {incr i} { lappend seq [expr {[lindex $seq end-1]+[lindex $seq end]}] } } # Store last number back in the session for the next request session set num_fibos $num_fibos }
The page is now in its final form.

There are a number of changes here, so let us go through them one by one.
We detect whether the user has clicked the Generate button by
checking the params
object for the presence of the
key numfibos
. The params
object in Woof!
holds all parameters received in the HTTP request through either
a query string in an HTTP GET request, or through an
HTTP POST request. If the parameter is present, we use its value
as the requested size of the sequence to be generated. Otherwise, we
maintain the original behaviour.
If the user input is invalid, we redirect them to an error
page. The redirect
method, like the url_for
method we saw earlier, takes an -action
argument which
generates a HTTP redirect to the
method showerror
.
We are almost done, but need to describe one final step - how the error description is passed to the error display page. We do that in the next section.