Web Oriented Object Framework

User Guide (Version 0.5b4)

Woof!
User Guide (Version 0.5b4)

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.

Quick Start Example 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.