We are all different; we all have various ideas about how our application should look and work. Our customers have their own opinions and, well, sometimes prejudices too. As a result, at some time in your Tapestry development you will certainly come to the point when you'll find the existing choice of components insufficient, and you might want to create a component of your own.
In a previous article we were playing with one of the core Tapestry components, DatePicker, and I tried to convince you that although this component is very good, it might not always be an ideal choice for date input. Today I am going to show you what I have done in a real development project when I needed an alternative way to accept a date input from the user.
The process of creating Tapestry components is very similar to the process of creating Tapestry pages. As a page is typically represented by three files, say, Home.html for the template, Home.page for the specification and Home.java for the class, in the same way a component is typically represented by three files as well: say, SomeComponent.html for the template, SomeComponent.jwc for the specification (jwc extension means “Java Web Component”) and SomeComponent.java for the class.
The only significant difference between components and pages is that components usually accept at least one parameter while pages don't. Everything else is very, very similar.
Okay, that was enough propaganda; let's get some practical experience now. First of all, we need to visualize what exactly we want to achieve. As our Swiss customer with a massive C programming background can't bear a fancy DatePicker, we need to suggest something more traditional. Perhaps three drop-down lists for month, day and year input will do. This way, especially if we use not numbers but descriptive names for months, there will be no space for misinterpreting user input (as in that example – the 6th of December or the 12th of June?). Even if the user enters something like the 31st of February, by accepting the date in lenient mode we'll automatically convert it into the second or third of March, as the case may be.
Here is a screen shot of what we want to create:
As we don't want to place three PropertySelection components, configure them and then write some code to interpret them as one piece of input every time we need to accept a date from our user, what we need is a custom component. We want to be able to just drop it on a page and connect it to some property of the page class through the component's binding. Let's see how we can achieve this.