Sunday, November 7, 2010

Scala exercise 6: Tackling the Wicket hierarchy mismatch problem

Introduction


This is the sixth exercise in my Scala exercises series. If you haven’t seen it before, you may want to start from the previous exercises. Below is exercise 6: Tackling the Wicket hierarchy mismatch problem.
Some people have alleged that a weakness in Wicket is that you have to keep the hierarchy of the component tree in sync with that of the HTML elements. For example, for the HTML code:

<html>
<form wicket:id="f">
<input type="text" wicket:id="num">
<input type="submit" value="OK">
</form>
<span wicket:id="result">10</span>
</html>

You would construct a component tree (in Scala) like:

class MyPage extends WebPage {
val f = new Form[MyPage]("f") {
override def onSubmit() {
...
}
}
add(f) //add the form to the page
val numField = new TextField[Int]("num")
f.add(numField) //add the text field to the form
val r = new Label("result")
add(r) //add the label to the page
}

The problem is that, if, say, you'd like to move the result span into the form, you must change the code accordingly:

class MyPage extends WebPage {
...
val r = new Label("result")
f.add(r) //you must add the label to the form, not to the page!
}

and a common problem is that we may forget to do so. While there is no easy way to solve this problem, you could make the Scala code reflect the HTML structure visually (and look more like a declarative UI):

class MyPage extends WebPage {
//the "ctx" represents a surrounding container context for the
//construction of child components
this containing { ctx =>
val f = ...
ctx.add(f) //add the form to the context (the page)
f containing { ctx =>
val numField = ...
ctx.add(numField) //add the text field to the context (the form)
}
val r = new Label("result")
ctx.add(r) //add the label to the context (the page)
}
}

Note that the Scala code reflects the structure of the HTML code so you can compare them visually. In addition, if you need to move the label into the form, you can simply cut and paste the construction code of the label into that context of the form:

class MyPage extends WebPage {
//the "ctx" represents a surrounding container context for the
this containing { ctx =>
val f = ...
ctx.add(f)
f containing { ctx =>
val numField = ...
ctx.add(numField)
//the following lines were simply cut and pasted into here
val r = new Label("result")
ctx.add(r)
}
}
}

Now, your task is to implement this solution by creating the necessary code. Try to do it now.
See the answer here.