Conditionals, Loops, and Bindings
So far you have seen the basic regarding how to call methods from within the content and how to use a form to pass input back to the code. These two techniques, simple though they are, represent the backbone of how Iowa works. By themselves, though, they are too limited to make the construction of powerful application really easy. Take, for instance, a form in which you want to do some validation of the input and then display some sort of error message if the input is not correct.
With just the techniques present so far, you could do it. You'd have to embed a call to some error_message() method that would return an error message if there had been an error in the form values, but would return nothing if the form had not been submitted. That starts entering into the realm of mixing your content with your code, though, and since Iowa provides such a nice, simple seperation of code from content, it would be nice to maintain that seperation as much as possible. So, there is another way of doing it.
Iowa has a couple of special tags for conditional inclusion of content. They are the <if> and the <unless> tags. Each tag is used with an oid attribute. The oid attribute names a method to invoke. The return value of that method is what is evaluated to determine if the content wrapped within the tag will be displayed. The <if> tag will display its content if the method returns a true value, while the <unless> tag displays its content if the method returns a false value. Their usage looks like this:
Main.html<html><head><title>Calculate The Hypotenuse Of A Right Triangle</title></head><body><p>Please enter two positive numbers into the fields belowand press the "Calculate" button. The hypotenuse of theright triangle that they describe will be calculated.</p><unless oid="no_errors"><p style="color: red">Error. Please recheck yournumbers. At least one of them is incorrect.</p></unless><form oid="calculate_hypotenuse">Side A <input type="text" size="4" maxlength="6" oid="side_a"> Side B <input type="text" size="4" maxlength="6" oid="side_b"> <input type="submit" value="Calculate" oid="calculate"></form><if oid="side_c"><p>The hypotenuse is: @side_c</p></if></body></html>
class Main < Iowa::Componentattr_accessor :side_a, :side_b, :side_c, :no_errorsdef awake@no_errors = trueenddef check_values@no_errors = true@no_errors = false unless @side_a > 0@no_errors = false unless @side_b > 0@no_errorsenddef calculate@side_a = @side_a.to_f@side_b = @side_b.to_f@side_c = check_values ? Math.sqrt(@side_a * @side_a + @side_b * @side_b) : nilendend
Here is the link to a live version of this hypotenuse calculator.
In this example, with both the <if> and the <unless> tags, the named method was an accessor method. If we wanted the application to give more detailed feedback on what was wrong, however, we might have written some methods like is_negative?() or is_numeric?() that would have performed a more sophisticated check than simply evaluating a variable for true or false.
This example also introduces another new item. Take a look at line 4 of Main.iwa. A method named awake() is being defined. This method is defined as an empty stub in Iowa::Component, intended to be overridden in the subclasses. It is called when a component is initially created, and it intended to be used to establish the initial state of the object. In our example we use it to set the initial state of the @no_errors variable.
Another method that is also stubbed out in Iowa::Component is the setup() method. While awake() is only called once, on creation of the component, setup() is called every time a component is displayed. This makes it useful for querying value from a database that may have changed from one view to the next, or for checking or querying other information which may have changed since the last time the component was displayed.
Bindings
Let's revisit the Hello World application from the last section, except this time our application is going to provide a link to redisplay itself. Also, below the current time will be a list showing each time the reload link was clicked as well as the time that it was clicked.
So, let's start with the stuff we already know how to do:
Main.html<html><head><title>Hello World!</title></head><body><h1>Hello World!</h1><p>The time is: @current_time</p></body></html>
class Main < Iowa::Componentdef current_timeTime.nowendend
So far this is all stuff that you have seen before. No problem. So, the next thing to do is to add a link that will reload the current page. Recall in the previous section where it was mentioned that if a method invoked to handle a form did not yield a new page, that the current page would instead be redisplayed? Well, <a> tags work exactly the same way in Iowa. The oid attribute will name the method to call, and so long as that method doesn't create a new component object to receive control, our current page will be displayed again.
So, add the following line to your HTML file after line 5:
<a oid="log_and_redisplay">Redisplay</a>
Then add the following lines to your code file, after your class declaration:
attr_reader :time_logdef awake@time_log = []enddef log_and_redisplay@time_log << Time.nowend
Now, if you test the application, you should have something like this.
It works, and as you see from the changing time, it is being redisplayed when you click the link. How should we display the log of times, though? Try this:
<p>Your log of page visits: @time_log</p>
Hmm. After the first time you redisplay the page, it's looking good, but subsequent clicks reveal a problem. That's not how you want the log to be shown. Instead, we want a vertical list of log entries, and we want Iowa to do most of the work for us. What is really needed is a way to iterate over the log entries, displaying an entry per line, without having to write a method to do the iteration and to generate the HTML. Bindings provide the answer.
First, add an accessor function:
attr_accessor :log_item
Next, in your code file, below the class definition, add the following block. This is the bindings definition section.
<?log_list {item = log_itemlist = time_log}?>
Now, delete the "Your log page..." line from your HTML and instead add these lines:
<ul oid="log_list"><li>@log_item</li></ul>
In this example we created a binding, log_list, that expects an array from time_log, and that uses log_item as the iterator. The <ul> tag, when used with an oid, becomes a dynamic tag. It repeats whatever it encloses once for each element of the array that is named in the binding. The value of that element gets assigned to the named iterator, and can be used within the repeated block. Here is the completed example.
One thing that is very neat, and powerful, about this particular mechanism is that the value of the iterator is remembered within the context of the repeated section, even for methods invoked from dynamic forms or links. That is, if each of the log items in the list were a dynamic link (an <a> tag with an oid attribute), when the method invoked by the link accesses @log_item, the value will be whatever the iterator held when that link was created, automatically. There is no need to write any explicit code to track these states.
For reference, Iowa defines several HTML tags as dynamic repeaters, just like the <ul> tag shown above. These are: <ul>, <ol>, <table>, and <tr>. Each of these is a simple subclass of <repeat> that provides a bit of convenient syntactic sugar. So, for example, the list of log items above could be written using <repeat> like so:
<ul><repeat oid="log_list"><li>@log_item</li></repeat></ul>
That will work in exactly the same way. It was just a little nicer to type and looks a little nicer to use the dynamic <ul> tag instead.
There are a few other interesting and occasionally useful facets to this type of binding. First of all, a binding may override the class of a dynamic tag. This is useful primarily as syntactic sugar for your HTML. For instance, consider the following binding and HTML snippet:
<?log_list:Repeat {item = log_itemlist = time_log}?>
<loglist oid="log_list">@log_item<br/></loglist>
There is no <loglist> tag in HTML, and Iowa doesn't specifically define one, either. However, since the addition of the oid attribute marks a tag as dynamic, Iowa finds the named binding and sees that the binding is defining a class for the tag. In this case, the class is Repeat. The binding overrides what Iowa sees in the content, so this particular <loglist> gets treated like a <repeat> tag, instead. This is syntactic sugar, pure and simple, and should be used sparingly. It may be useful, however, to make specific iterator uses easier for the HTML designer to understand and work with, or to make some areas of the source content more self documenting.
Second, any binding that starts with a digit, quote character, or colon is passed through an eval, and the result of that eval used as the binding value. So, for instance
list = "#{1+2}"
would assign a value of 3 as the sole item in a list. Or, for a slightly more useful example (although the syntax of it is ugly right now):
list = '';1..10
The empty quotes are just there to clue the binding parser in to the fact that we want it to evaluate the binding as Ruby code. We then populate the list with an array of the digits from 1 to 10. This is a useful shortcut for bindings that would otherwise use trivial methods. It lets the developer put the method code right into the binding and avoid having to put a named method into the component's class. In the next release of Iowa there will be a less ugly way of embedding code directly into the binding.
Now, consider for a moment that in your application you want to have a row of buttons. Rather than statically coding the labels on each of the buttons, however, you want the labels on the buttons to be determined by some set of data in your application. You also don't want to have to write code to generate the HTML. What do you do?
You use a binding, of course! For the next example, assume that the code provides an array of number in @ary, and you want to iterate through those numbers, creating a button for each number.
Main.iwa<?number_list {item = numberlist = ary}number_button {action = :number_pressedvalue = number}?>
<repeat oid="number_list"><input type="submit" oid="number_button"></repeat>
The second binding, the one labeled number_button, is the interesting one. It is assigning the iterator for the number_list as the value of the submit button. And since the value of a submit button determines its label onscreen, the buttons will end up labeled according to the values of the iterator. Here is a link to a reverse polish notation calculator that uses this exact technique to create all of the buttons on the calculator.


