Then open downloaded zip and copy required structure into previous generated project. Css and Js folders into resources directory, and rename index.html to index.jsp and copy it to views directory.
If you deploy application a white screen should be showed but without any client/server error.
Let's start creating next html form.
Add @import url(http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz); on top of CSS file.This will make a nice font available from Google Fonts directory.
Better than before, see how only modifying CSS, form layout is modified.
And now let's start with CSS3 magic.
First trick is adding shadows and gradients to form.
Next lines add some mouse over effects into form elements.
And to finish applying styles, we are going to modify submit button.
Remove input[type="submit"] from button and input style.
And add next lines into CSS file:
CSS magic is over, now it is time to start with server side.
If you look careful Spring taglibs, you will see that you cannot create for example email input types directly or URL types to cite a few. So I decided to use a new template engine called Thymeleaf, that offers a really nice approach for integrating HTML 5 with Spring MVC applications.
The main goal of Thymeleaf is to provide an elegant and well-formed way of creating HTML 5 templates. Its Standard and SpringStandard dialects allow you to create powerful natural templates, that can be correctly displayed by browsers and therefore work also as static prototypes. This is possible due the absence of taglibs like <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>.
First thing to do is change index.jsp to index.html, and change ViewResolver to Thymeleaf ViewResolver:
First add Thymeleaf dependencies into pom and then modify servlet-context.xml to register TempateResolver, TemplateEngine and ThymeleafViewResolver and remove the deault view resolver.
Next step is modeling our form to a model class, and modify Spring Controller to manage form submition.
Model class is not shown because is a simple POJO with form fields. Let's see how controller is modified.
Open HomeController class and create two methods (GET, POST) to deal with HTML5 form. Note that it is a typical Spring Form Controller;
Open index.html and make next changes:
Add Thymeleaf namespace on html tag.
<html xmlns:th="http://www.thymeleaf.org">
Then change form tag with two new attributes, one with object's model name (form backing object) and other one with submition URL.
<form action="#" th:object="${messageInfo}" th:action="@{/}" method="post">
Next thing to do is change each form element with th:value attribute containing backing object property name.
<input type="text" name="name" value="" id="name" placeholder="Your Name" required="required" autofocus="autofocus" th:value="*{name}"/>
And more few changes should be performed:
Use DOCTYPE instead of doctype
At time of writing this post, html5boilporate introduces link tag without closing, so Thymeleaf parser will throw an exception if is executed as is, so let's terminate link tag and meta tags.
And finally last change is required because of xhtml correctness:
<script> tag is surrounded with CDATA tags. See explanation here: http://javascript.about.com/library/blxhtml.htm.
Now you can deploy application and your HTML5+CSS3 form is displayed and data submitted is displayed through server console and form page is reloaded with introduced data. And now I am going to explain what are those strange expressions in form and then we will add a new page.
Inside each Thymelef attribute four kind of expressions can be used:
- ${...} are Spring EL expressions and are executed on model attributes.
- *{...} are expressions executed on the form backing bean, it is like a pointer to form object (root).
- #{...} are for internationalization.
- @{...} are link expressions to rewrite URLs.
And before jumping to next section try this, instead of opening index.html from http://localhost:..... try to open from your drive file://.... and I suppose you see that that's not a nice prototype because no styling is applied. This happens because we are using CSS location as:
<link rel="stylesheet" href="css/style.css"/>
HTML file is at /src/main/webapp/WEB-INF/views/ and this directory does not contain css folder. And now you can think that I have not told you the true about prototyping with Thymeleaf, but wait trust me and change that line to:
<link rel="stylesheet" href="../../css/style.css" th:href="@{/css/style.css}"/>
And open again, and wow now you can see it, a real page as one generated by the server. What we have changed is that when a browser opens HTML file without using template engine (offline), href attribute is used, but when page is online (and requested file acts as a template), th:href attribute is used.
Listing Messages:
Let's start creating a new HTML file to display all inserted messages and apply some styling with CSS.
Then create a file called list.html in same level of index.html:
In this case we are using another nice feature of Thymeleaf, collection iteration. With th:each you are iterating over a collection of elements. See that rowStat variable can be used for retrieving column information like number of column. And also see how we are defining default values between td tags, so this file is a prototype too.
Next step is changing our controller, so homeForm (renamed to showResults) method returns a list of messages:
Using a simple list as repository is not a good design, but for teaching purpose is enough. See that view name is set to list, and list of messageForm are sent back with model name used in th:each attribute.
Internationalization:
Next step is internationalizing the application. For this reason we create a message properties file (messages_en_US.properties) into src/main/resources/locale:
<th th:text="#{theader.count}"></th>
<label for="name" th:text="#{theader.name}">Name: </label>
And although internationalization is used, web page is still a prototype.
It seems like application is working well, but it has one problem. Try next sequence of events:
1. Add a new message.
2. When list of all messages are shown, refresh the page (F5).
And surprise the same message is added too, so now we have two repeated messages, but you have only inserted one.
To fix this problem we must change our controller and use redirect keyword on create method to redirect to a method of controller that finds all inserted messages.
When a new message is created (create method), a redirect to /list is returned, then showResults method is called, and returns a list with all inserted messages. Remember to change th:action from form tag to /insert too.
And now if you execute the same process as before, no multiple insertions occur.
Validation:
And as final step let's see how to implement validation with Thymeleaf.
First thing is adding Jsr-303 provider into our pom. In this case Hibernate-Validator.
Next step is changing our model by for example creating a length constraint in phone field:
@Length(min=9)
private String phone;
To trigger validation of a @Controller input, you must annotate input arguments with @Valid. So our controller is modified to:
First a new CSS style is created for showing error message:
And finally in index.html a new div is created for showing errors:
For showing errors, #fields variable is used. This variable is provided by Thymeleaf and contains all errors bound by Validation Framework. Note that star '*' is used as errors function parameters for returning all errors produced by all form fields, but Thymeleaf allows you to specify only one particular field.
Conclusions:
From this post I have learned some interesting points:
- With new HTML5 tags, some Javascript validation (like entering well-formatted email) is not required anymore.
- CSS 3 shadows and gradients properties allow us to create amazing forms without using complicated structures of images.
- Thymeleaf is an amazing template engine, in fact for me a real way for creating prototypes and final code at once.
- Thymeleaf is a young project, and for example does not support jQuery by default, but exists a Thymeleaf dialect that integrate it. I think that in nearest future it will be a template engine to be consider.
Hope you find Thymeleaf useful too.
Download Code.