Finally, we need to create a component class. It will bring together all the constituents and make them work together toward the goal that we’ve defined: public abstract class DateInput extends BaseComponent implements PageBeginRenderListener {
@Parameter(required = true) public abstract Date getDate(); public abstract void setDate(Date d);
private Calendar c = Calendar.getInstance();
public void pageBeginRender(PageEvent event) { c.setTime(getDate() == null ? new Date() : getDate()); }
public IPropertySelectionModel getDaysModel() { return new DayModel(); }
public IPropertySelectionModel getMonthsModel() { return new LocalisedMonthsModel(getPage().getLocale()); }
public IPropertySelectionModel getYearsModel() { return new YearModel(); }
public int getDay() { return c.get(Calendar.DATE); }
public void setDay(int day) { c.set(Calendar.DATE, day); }
public int getMonth() { return c.get(Calendar.MONTH); }
public void setMonth(int month) { c.set(Calendar.MONTH, month); }
public int getYear() { return c.get(Calendar.YEAR); }
public void setYear(int year) { c.set(Calendar.YEAR, year); setDate(c.getTime()); } } Most of this code is very simple, but there are a few points that are worth commenting upon. There are three methods returning models to PropertySelection components, and one of them is slightly unusual: public IPropertySelectionModel getMonthsModel() { return new LocalisedMonthsModel(getPage().getLocale()); } Here you can see how our component gets a reference to the page, onto which it will be placed (the getPage() method is available to every component), and then asks the page for the current Locale. The page’s answer is then passed to the LocalisedMonthsModel constructor, so that the names for the months were shown in an appropriate language. Perhaps the most interesting fragment of this code is how we define the parameter required by our custom component: @Parameter(required = true) public abstract Date getDate(); public abstract void setDate(Date d); You should already be used to abstract getters and setters – our way of asking Tapestry to implement whatever is needed automatically. Here we also clarify that this will be a parameter named date, and this parameter is required. This means that if someone will want to use DateInput, they will need to provide a binding named date, and if they don’t, Tapestry will throw an exception. Using the abstract getter, we can obtain in our code the value provided by the page class through the required binding, and when the user submits the results of his or her input, we’ll use the abstract setter to report to the page on which the date was selected.
blog comments powered by Disqus |
|
|
|
|
|
|
|