extending spring form tag library attributes

2020-02-26 02:36发布

问题:

I'm using Spring's form tag library in a Spring MVC application that I am developing. The company I am working for has implemented some company-wide policies based on the definition of custom attributes for certain tags. For instance, by default (though the inclusion of a standard javascript file) all tags have their values automatically converted to upper case. In order to disable this one would define their tag with a custom attribute in the following way:

<input type="text" uppercase="false" />

The problem is that the addition of these custom attributes to a spring:form tag causes an error at runtime. I've pasted the error below.

org.apache.jasper.JasperException: /WEB-INF/jsp/reportCriteria.jsp(45,5) Attribute uppercase invalid for tag input according to TLD

My question is: is there any way to extend the TLD to allow for these attributes, or is there any other way add these custom attributes to these spring:form tags?

回答1:

It's implemented in Spring 3.0 (SPR-5931).



回答2:

Ok, 2 years later... here we go!

HOW TO CREATE OUR OWN TAG EXTENDING CLASSIC ONE WITH NEW ATTRIBUTES IN SPRING MVC 3


1. Create your own taglib.tld

You need to create your own TLD file. There you are going to add the new attribute you are going to use. The best option is copy/paste spring-form.tld. You can find it in spring-mvc package (org.springframework.web.servlet-.jar).Search in META-INF folder.

Feel free to put it directly inside WEB-INF or in a subfolder. I putted it in /WEB-INF/tld.

Now search inside your new TLD file for the tag you are going to modify. I modified input tag, so i had to search for:

  ...
  <tag>
  <description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
  <name>input</name>
  <tag-class>org.domain.tags.CustomTags</tag-class>
  <body-content>empty</body-content>
  <attribute>
  ...

Copy from to and paste it below. Change the of the new tag for your own name. Mine was myInput. So now we have this:

  ...
  <tag>
  <description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
  <name>input</name>
  <tag-class>org.springframework.web.servlet.tags.form.InputTag</tag-class>
  <body-content>empty</body-content>
  <attribute>
  ...
  </tag>

  <tag>
  <description>Renders an HTML 'input' tag with type 'text' using the bound value.</description>
  <name>myInput</name>
  <tag-class>org.domain.tags.CustomTags</tag-class>
  <body-content>empty</body-content>
  <attribute>
  ...
  </tag>

SUMMARY: now I have a new file called taglib.tld here: /WEB-INF/tld/taglib.tld. Pay attention to the <tag-class> part

In your own new tag add a new attribute (copy/paste another one) call render.

<attribute>
  <description>Enables/Disables the field rendering</description>
  <name>render</name>
  <required>false</required>
  <rtexprvalue>true</rtexprvalue>
  <type>java.lang.Boolean</type>
</attribute>

Now we have created the taglib file we need. Let's see how to use it.

2. Create your own handler

Now we are going to create the class that will handle the new attribute (and the classic ones). I created the class CustomTags.java en el paquete org.domain.tags. Let's see first the code and explain it:

package org.domain.tags;

import javax.servlet.jsp.JspException;
import org.springframework.web.servlet.tags.form.InputTag;
import org.springframework.web.servlet.tags.form.TagWriter;

public class CustomTags extends InputTag {

private static final long serialVersionUID = 1L;
private boolean render;

public boolean isRender() {
  return render;
}

public void setRender(boolean render) {
  this.render = render;
}

protected int writeTagContent(TagWriter tagWriter) throws JspException {
  if(render){
    super.writeTagContent(tagWriter);
    return SKIP_BODY;
  }
  else
    return SKIP_BODY;
  }
}

Of course, if we are going to add some features to the Input tag of Spring framework, we must extend it in order to mantain the rest of the features. As you can see, we have just added the render private attribute as boolean (in taglib.tld we also put it).

We have added to the getter and setter methods for this attribute.

Finally we have overwrite the writeTagContent method in order to make the JSP do what we want. In this case we want the input field to be shown if render is true. Otherwise the field can't be shown. That's why we call the writeTagContent of the parent class.

If we need to make some changes on the tag behaviour, this method is the right place to do them.

3. Using the new tag.

Now we only need a JSP with a form to use the new tag. It's easy to do, so i only let here the code:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix = "newtags" uri = "/WEB-INF/tld/taglib.tld" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>Spring 3.0 MVC Series: Welcome World</title>
</head>
<body>
  <h1>User Data</h1>
  Please, fill the fields with your information:<br>
  <newtags:form name="userForm" id="userForm" modelAttribute="userForm" action="user.htm" method="POST">
    Name: <newtags:myInput type="text" name="textName" path="userName" render="true" size="50" /><newtags:errors path="userName" /><br>
    Surname: <newtags:myInput type="text" name="textSurname" path="userSurname" render="true" size="50" /><newtags:errors path="userSurname" /><br>
    Age: <newtags:myInput type="text" name="textAge" path="userAge" render="true" size="2" /><newtags:errors path="userAge" /><br>
    Example: <newtags:myInput type="text" name="textSurname" render="false" size="20" path="userSurname"/>
    <hr>
    <input type="submit" value="Next" />
  </newtags:form>
</body>
</html>

Now instead of calling springframework tld, we call our own TLD. As you can see the only field that is not going to be shown is Example one.

Good Luck all!