Extend h:outputText for custom functionality
Asked Answered
H

1

5

I have been using JSF + RF for over 2 years and have'nt had a chance to extend the existing capabilities of components.

Now the requirement is I have to trim the string and display it if it is more than 25 characters.

This has been achieved as below

                        <c:choose>
                            <c:when test="#{fn:length(teststep.name) > 25}">
                                <h:outputText title="#{teststep.name}" value="#{fn:substring(teststep.name, 0, 25)}..."/>
                            </c:when>
                            <c:otherwise>
                                <h:outputText title="#{teststep.name}" value="#{teststep.name}"/>
                            </c:otherwise>
                        </c:choose>

But I use this code in lot many places (and want to avoid boilerplate code of 8 lines everytime) so thought of custom h:outputText to provide trim functionality.

Could you let me know how would I write a custom tag in JSF

Regards, Satya

Hectometer answered 22/2, 2012 at 14:16 Comment(0)
B
11

Assuming that you're using JSP not Facelets, put the content in a .tag file in /WEB-INF, like /WEB-INF/tags/outputLimitedText.tag.

<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<c:choose>
    <c:when test="#{fn:length(value) > maxlength}">
        <h:outputText title="#{value}" value="#{fn:substring(value, 0, maxlength)}..."/>
    </c:when>
    <c:otherwise>
        <h:outputText title="#{value}" value="#{value}"/>
    </c:otherwise>
</c:choose>

Then you can reference it as follows:

<%@ taglib prefix="my" tagdir="/WEB-INF/tags" %> 
...
<my:outputLimitedText value="#{teststep.name}" maxlength="25" />

You could also use a Converter.

<h:outputText title="#{teststep.name}" value="#{teststep.name}">
    <f:converter converterId="substringConverter" />
    <f:attribute name="maxlength" value="25" />
</h:outputText>

with

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    String string = (String) value;
    int maxlength = Integer.valueOf((String) component.getAttributes().get("maxlength"));

    if (string.length() > maxlength) {
        return string.substring(0, maxlength) + "...";
    } else {
        return string;
    }
}

You could also create a custom EL function. So that you end up with

<h:outputText title="#{teststep.name}" value="#{util:ellipsis(teststep.name, 25)}">

A concrete example of the EL function is given in this answer: How to concatenate Strings in EL?

Bedivere answered 22/2, 2012 at 14:20 Comment(3)
I have tried the 1st solution and that didnt impress me :) but would like to do something like <h:outputText title="#{value}" value="#{value}" trimByChars="25"/> . Is that by any chance possible to still retain features of h:outputText and only add some more capabilities?Hectometer
I will give a try for the third option, seems to be some new learning for me :) . Thanks a lot BalusCHectometer
Adding a new attribute to an existing component is only possible by a custom component, not a custom tag. This is a very tedious work. You've to copy all existing tag attributes as it's not possible to inherit from existing tags. Easier would be to provide the extra attribute as <f:attribute> and override the default Renderer.Bedivere

© 2022 - 2024 — McMap. All rights reserved.