jsf - 如何制作JSF复合组件的网格?

标签 jsf jsf-2 grid alignment composite-component

我在 panelGrids 中有很多 outputLabel 和 inputText 对

<h:panelGrid columns="2">
  <h:outputLabel value="label1" for="inputId1"/>
  <h:inputText id="inputId1/>

  <h:outputLabel value="label2" for="inputId2"/>
  <h:inputText id="inputId2/>

  ...
</h:panelGrid>

我希望对所有这些都具有一些行为:例如每个输入文本具有相同的验证或相同的大小。所以我创建了一个复合组件,其中只包含一个outputLabel和一个inputText

<my:editField value="field1"/>
<my:editField value="field2"/>

但是现在当我将它们放入 gridPanel 中时,它们不会根据标签文本的长度进行对齐。我明白原因,但不知道如何解决。

最佳答案

复合组件确实被渲染为单个组件。您想改用 Facelet 标记文件。它的渲染与输出的渲染完全一样。下面是一个启动示例,假设您需要一个 3 列表单,并在第三列中包含消息字段。

/WEB-INF/tags/input.xhtml中创建标记文件(或者当您想要在要包含在 /META-INF 中的 JAR 文件中提供标签时,在 /WEB-INF/lib 中)。

<ui:composition
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <c:set var="id" value="#{not empty id ? id : (not empty property ? property : action)}" />
    <c:set var="required" value="#{not empty required and required}" />

    <c:choose>
        <c:when test="#{type != 'submit'}">
            <h:outputLabel for="#{id}" value="#{label}&#160;#{required ? '*&#160;' : ''}" />
        </c:when>
        <c:otherwise>
            <h:panelGroup />
        </c:otherwise>
    </c:choose>

    <c:choose>
        <c:when test="#{type == 'text'}">
            <h:inputText id="#{id}" value="#{bean[property]}" label="#{label}" required="#{required}">
                <f:ajax event="blur" render="#{id}-message" />
            </h:inputText>
            <h:message id="#{id}-message" for="#{id}" />
        </c:when>
        <c:when test="#{type == 'password'}">
            <h:inputSecret id="#{id}" value="#{bean[property]}" label="#{label}" required="#{required}">
                <f:ajax event="blur" render="#{id}-message" />
            </h:inputSecret>
            <h:message id="#{id}-message" for="#{id}" />
        </c:when>
        <c:when test="#{type == 'select'}">
            <h:selectOneMenu id="#{id}" value="#{bean[property]}" label="#{label}" required="#{required}">
                <f:selectItems value="#{options.entrySet()}" var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
                <f:ajax event="change" render="#{id}-message" />
            </h:selectOneMenu>
            <h:message id="#{id}-message" for="#{id}" />
        </c:when>
        <c:when test="#{type == 'submit'}">
            <h:commandButton id="#{id}" value="#{label}" action="#{bean[action]}" />
            <h:message id="#{id}-message" for="#{id}" />
        </c:when>
        <c:otherwise>
            <h:panelGroup />
            <h:panelGroup />
        </c:otherwise>            
    </c:choose>
</ui:composition>

/WEB-INF/example.taglib.xml中定义它(或者当您想在要包含在 /META-INF 中的 JAR 文件中提供标签时,在 /WEB-INF/lib 中):

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0">
    <namespace>http://example.com/jsf/facelets</namespace>
    <tag>
        <tag-name>input</tag-name>
        <source>tags/input.xhtml</source>
    </tag>
</facelet-taglib>

/WEB-INF/web.xml中声明taglib的用法(当标签由 /WEB-INF/lib 中包含的 JAR 文件提供时,不需要这样做!JSF 将自动加载 *.taglib.xml 中的所有 /META-INF 文件)。

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/example.taglib.xml</param-value>
</context-param>

(多个taglib文件可以用分号分隔;)

最后只需在主页模板中声明它即可。

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:my="http://example.com/jsf/facelets"
>
    <h:head>
        <title>Facelet tag file demo</title>
    </h:head>
    <h:body>
        <h:form>
            <h:panelGrid columns="3">
                <my:input type="text" label="Username" bean="#{bean}" property="username" required="true" />
                <my:input type="password" label="Password" bean="#{bean}" property="password" required="true" />
                <my:input type="select" label="Country" bean="#{bean}" property="country" options="#{bean.countries}" />
                <my:input type="submit" label="Submit" bean="#{bean}" action="submit" />
            </h:panelGrid>
        </h:form>
    </h:body>
</html>

(#{bean.countries} 应返回 Map<String, String>,其中国家/地区代码作为键,国家/地区名称作为值)

屏幕截图:

enter image description here

希望这有帮助。

关于jsf - 如何制作JSF复合组件的网格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5713718/

相关文章:

java - JSF 以清晰的方式显示条件文本

java - 在 ui :repeat manually 中创建多个 Ul

ajax - richfaces popupPanel : commandButton requires two clicks

jsf-2 - JSF双重提交表单数据

javafx制作按钮网格

html - 侧边栏旁边带有嵌套 100% 宽度标题的网格系统?

jsf - com.sun.faces.config.InitFacesContext.cleanupInitMaps 中的空指针异常

jsf - "the JSF runtime"是什么意思, "javax.faces.webapp.FacesServlet"有何关系?

jsf-2 - Primefaces p :calendar, 值设置不正确

javascript - EXT JS 拖动网格列时自动滚动容器