[FRAMEWORK] 스프링 사용자정의 태그

13.9. Using Spring's form tag library
As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant.

Unlike other form/input tag libraries, Spring's form tag library is integrated with Spring Web MVC, giving the tags access to the command object and reference data your controller deals with. As you will see in the following examples, the form tags make JSPs easier to develop, read and maintain.

Let's go through the form tags and look at an example of how each tag is used. We have included generated HTML snippets where certain tags require further commentary.

13.9.1. Configuration
The form tag library comes bundled in spring.jar. The library descriptor is called spring-form.tld.

To use the tags from this library, add the following directive to the top of your JSP page:

[%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %]
... where form is the tag name prefix you want to use for the tags from this library.

13.9.2. The form tag
This tag renders an HTML 'form' tag and exposes a binding path to inner tags for binding. It puts the command object in the PageContext so that the command object can be accessed by inner tags. All the other tags in this library are nested tags of the form tag.

Let's assume we have a domain object called User. It is a JavaBean with properties such as firstName and lastName. We will use it as the form backing object of our form controller which returns form.jsp. Below is an example of what form.jsp would look like:

[form:form]
[table]
[tr]
[td]First Name:[/td]
[td][form:input path="firstName" /][/td]
[/tr]
[tr]
[td]Last Name:[/td]
[td][form:input path="lastName" /][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form:form]
The firstName and lastName values are retrieved from the command object placed in the PageContext by the page controller. Keep reading to see more complex examples of how inner tags are used with the form tag.

The generated HTML looks like a standard form:

[form method="POST"]
[table]
[tr]
[td]First Name:[/td]
[td][input name="firstName" type="text" value="Harry"/][/td]
[td][/td]
[/tr]
[tr]
[td]Last Name:[/td]
[td][input name="lastName" type="text" value="Potter"/][/td]
[td][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form]
The preceding JSP assumes that the variable name of the form backing object is 'command'. If you have put the form backing object into the model under another name (definitely a best practice), then you can bind the form to the named variable like so:

[form:form commandName="user"]
[table]
[tr]
[td]First Name:[/td]
[td][form:input path="firstName" /][/td]
[/tr]
[tr]
[td]Last Name:[/td]
[td][form:input path="lastName" /][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form:form]
13.9.3. The input tag
This tag renders an HTML 'input' tag with type 'text' using the bound value. For an example of this tag, see Section 13.9.2, “The form tag”.

13.9.4. The checkbox tag
This tag renders an HTML 'input' tag with type 'checkbox'.

Let's assume our User has preferences such as newsletter subscription and a list of hobbies. Below is an example of the Preferences class:

public class Preferences {

private boolean receiveNewsletter;

private String[] interests;

private String favouriteWord;

public boolean isReceiveNewsletter() {
return receiveNewsletter;
}

public void setReceiveNewsletter(boolean receiveNewsletter) {
this.receiveNewsletter = receiveNewsletter;
}

public String[] getInterests() {
return interests;
}

public void setInterests(String[] interests) {
this.interests = interests;
}

public String getFavouriteWord() {
return favouriteWord;
}

public void setFavouriteWord(String favouriteWord) {
this.favouriteWord = favouriteWord;
}
}
The form.jsp would look like:

[form:form]
[table]
[tr]
[td]Subscribe to newsletter?:[/td]
[%-- Approach 1: Property is of type java.lang.Boolean --%]
[td][form:checkbox path="preferences.receiveNewsletter"/][/td]
[td] [/td]
[/tr]

[tr]
[td]Interests:[/td]
[td]
[%-- Approach 2: Property is of an array or of type java.util.Collection --%]
Quidditch: [form:checkbox path="preferences.interests" value="Quidditch"/]
Herbology: [form:checkbox path="preferences.interests" value="Herbology"/]
Defence Against the Dark Arts: [form:checkbox path="preferences.interests"
value="Defence Against the Dark Arts"/]
[/td]
[td] [/td]
[/tr]
[tr]
[td]Favourite Word:[/td]
[td]
[%-- Approach 3: Property is of type java.lang.Object --%]
Magic: [form:checkbox path="preferences.favouriteWord" value="Magic"/]
[/td]
[td] [/td]
[/tr]
[/table]
[/form:form]
There are 3 approaches to the checkbox tag which should meet all your checkbox needs.

Approach One - When the bound value is of type java.lang.Boolean, the input(checkbox) is marked as 'checked' if the bound value is true. The value attribute corresponds to the resolved value of the setValue(Object) value property.

Approach Two - When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.

Approach Three - For any other bound value type, the input(checkbox) is marked as 'checked' if the configured setValue(Object) is equal to the bound value.


Note that regardless of the approach, the same HTML structure is generated. Below is an HTML snippet of some checkboxes:

[tr]
[td]Interests:[/td]
[td]
Quidditch: [input name="preferences.interests" type="checkbox" value="Quidditch"/]
[input type="hidden" value="1" name="_preferences.interests"/]
Herbology: [input name="preferences.interests" type="checkbox" value="Herbology"/]
[input type="hidden" value="1" name="_preferences.interests"/]
Defence Against the Dark Arts: [input name="preferences.interests" type="checkbox"
value="Defence Against the Dark Arts"/]
[input type="hidden" value="1" name="_preferences.interests"/]
[/td]
[td] [/td]
[/tr]
What you might not expect to see is the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value will not be sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore ("_") for each checkbox. By doing this, you are effectively telling Spring that “the checkbox was visible in the form and I want my object to which the form data will be bound to reflect the state of the checkbox no matter what”.

13.9.5. The radiobutton tag
This tag renders an HTML 'input' tag with type 'radio'.

A typical usage pattern will involve multiple tag instances bound to the same property but with different values.

[tr]
[td]Sex:[/td]
[td]Male: [form:radiobutton path="sex" value="M"/] [br/]
Female: [form:radiobutton path="sex" value="F"/] [/td]
[td] [/td]
[/tr]
13.9.6. The password tag
This tag renders an HTML 'input' tag with type 'password' using the bound value.

[tr]
[td]Password:[/td]
[td]
[form:password path="password" /]
[/td]
[/tr]
Please note that by default, the password value is not shown. If you do want the password value to be shown, then set the value of the 'showPassword' attribute to true, like so.

[tr]
[td]Password:[/td]
[td]
[form:password path="password" value="^76525bvHGq" showPassword="true" /]
[/td]
[/tr]
13.9.7. The select tag
This tag renders an HTML 'select' element. It supports data binding to the selected option as well as the use of nested option and options tags.

Let's assume a User has a list of skills.

[tr]
[td]Skills:[/td]
[td][form:select path="skills" items="${skills}"/][/td]
[td][/td]
[/tr]
If the User's skill were in Herbology, the HTML source of the 'Skills' row would look like:

[tr]
[td]Skills:[/td]
[td][select name="skills" multiple="true"]
[option value="Potions"]Potions[/option]
[option value="Herbology" selected="true"]Herbology[/option]
[option value="Quidditch"]Quidditch[/option][/select][/td]
[td][/td]
[/tr]
13.9.8. The option tag
This tag renders an HTML 'option'. It sets 'selected' as appropriate based on the bound value.

[tr]
[td]House:[/td]
[td]
[form:select path="house"]
[form:option value="Gryffindor"/]
[form:option value="Hufflepuff"/]
[form:option value="Ravenclaw"/]
[form:option value="Slytherin"/]
[/form:select]
[/td]
[/tr]
If the User's house was in Gryffindor, the HTML source of the 'House' row would look like:

[tr]
[td]House:[/td]
[td]
[select name="house"]
[option value="Gryffindor" selected="true"]Gryffindor[/option]
[option value="Hufflepuff"]Hufflepuff[/option]
[option value="Ravenclaw"]Ravenclaw[/option]
[option value="Slytherin"]Slytherin[/option]
[/select]
[/td]
[/tr]
13.9.9. The options tag
This tag renders a list of HTML 'option' tags. It sets the 'selected' attribute as appropriate based on the bound value.

[tr]
[td]Country:[/td]
[td]
[form:select path="country"]
[form:option value="-" label="--Please Select"/]
[form:options items="${countryList}" itemValue="code" itemLabel="name"/]
[/form:select]
[/td]
[td][/td]
[/tr]
If the User lived in the UK, the HTML source of the 'Country' row would look like:

[tr]
[td]Country:[/td]
[tr]
[td]Country:[/td]
[td]
[select name="country"]
[option value="-"]--Please Select[/option]
[option value="AT"]Austria[/option]
[option value="UK" selected="true"]United Kingdom[/option]
[option value="US"]United States[/option]
[/select]
[/td]
[td][/td]
[/tr]
[td][/td]
[/tr]
As the example shows, the combined usage of an option tag with the options tag generates the same standard HTML, but allows you to explicitly specify a value in the JSP that is for display only (where it belongs) such as the default string in the example: "-- Please Select".

13.9.10. The textarea tag
This tag renders an HTML 'textarea'.

[tr]
[td]Notes:[/td]
[td][form:textarea path="notes" rows="3" cols="20" /][/td]
[td][form:errors path="notes" /][/td]
[/tr]
13.9.11. The hidden tag
This tag renders an HTML 'input' tag with type 'hidden' using the bound value. To submit an unbound hidden value, use the HTML input tag with type 'hidden'.

[form:hidden path="house" /]

If we choose to submit the 'house' value as a hidden one, the HTML would look like:

[input name="house" type="hidden" value="Gryffindor"/]

13.9.12. The errors tag
This tag renders field errors in an HTML 'span' tag. It provides access to the errors created in your controller or those that were created by any validators associated with your controller.

Let's assume we want to display all error messages for the firstName and lastName fields once we submit the form. We have a validator for instances of the User class called UserValidator.

public class UserValidator implements Validator {

public boolean supports(Class candidate) {
return User.class.isAssignableFrom(candidate);
}

public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.");
}
}
The form.jsp would look like:

[form:form]
[table]
[tr]
[td]First Name:[/td]
[td][form:input path="firstName" /][/td]
[%-- Show errors for firstName field --%]
[td][form:errors path="firstName" /][/td]
[/tr]

[tr]
[td]Last Name:[/td]
[td][form:input path="lastName" /][/td]
[%-- Show errors for lastName field --%]
[td][form:errors path="lastName" /][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form:form]
If we submit a form with empty values in the firstHame and lastName fields, this is what the HTML would look like:

[form method="POST"]
[table]
[tr]
[td]First Name:[/td]
[td][input name="firstName" type="text" value=""/][/td]
[%-- Associated errors to firstName field displayed --%]
[td][span name="firstName.errors"]Field is required.[/span][/td]
[/tr]

[tr]
[td]Last Name:[/td]
[td][input name="lastName" type="text" value=""/][/td]
[%-- Associated errors to lastName field displayed --%]
[td][span name="lastName.errors"]Field is required.[/span][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form]
What if we want to display the entire list of errors for a given page? The example below shows that the errors tag also supports some basic wildcarding functionality.

path="*" - displays all errors

path="lastName*" - displays all errors associated with the lastName field

The example below will display a list of errors at the top of the page, followed by field-specific errors next to the fields:

[form:form]
[form:errors path="*" cssClass="errorBox" /]
[table]
[tr]
[td]First Name:[/td]
[td][form:input path="firstName" /][/td]
[td][form:errors path="firstName" /][/td]
[/tr]
[tr]
[td]Last Name:[/td]
[td][form:input path="lastName" /][/td]
[td][form:errors path="lastName" /][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]
[/table]
[/form:form]
The HTML would look like:

[form method="POST"]
[span name="*.errors" class="errorBox"]Field is required.[br/]Field is required.[/span]
[table]
[tr]
[td]First Name:[/td]
[td][input name="firstName" type="text" value=""/][/td]
[td][span name="firstName.errors"]Field is required.[/span][/td]
[/tr]

[tr]
[td]Last Name:[/td]
[td][input name="lastName" type="text" value=""/][/td]
[td][span name="lastName.errors"]Field is required.[/span][/td]
[/tr]
[tr]
[td colspan="3"]
[input type="submit" value="Save Changes" /]
[/td]
[/tr]

댓글

이 블로그의 인기 게시물

[LINUX] CentOS 부팅시 오류 : UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY

[MSSQL] 데이터베이스가 사용 중이어서 배타적으로 액서스할 수 없습니다

구글코랩) 안전Dream 실종아동 등 검색 오픈API 소스를 공유합니다. (구글드라이브연동, 이미지 수집 소스)