JSF / Seam中的动态ID

时间:2008-11-25 09:17:38

标签: jsf seam

我正在研究的S​​eam应用程序遇到了一些问题,我想知道是否有人知道如何绕过它。我的应用程序中有一个表单,它使用AJAX显示某些输入框,具体取决于下拉框中的项目。除了在输入框中设置ID之外,代码工作正常。看起来JSF不允许我通过变量设置ID。标签中的“for”等其他属性也没问题。这里有一些代码解释了我的意思:

<ui:repeat value="#{serviceHome.instance.serviceSettings}" var="currSetting" >
  <li>
    <!-- Imagine the below works out as "settingABC" -->
    <c:set var="labelKey" value="setting#{jsfUtils.removeWhitespace(currSetting.key.name)}" />

    <!-- Labelkey is correctly added into this input so for = "settingABC" -->
    <h:outputLabel for="#{labelKey}" styleClass="required generated" value="#{currSetting.key.name}:"/>

    <s:decorate styleClass="errorwrapper">

      <!-- Labelkey ISN'T correctly added into this input. Instead we just get "setting" -->
      <h:inputText id="#{labelKey}" value="#{currSetting.value}"/>

      <a4j:outputPanel ajaxRendered="true">
        <h:message for="#{labelKey}" styleClass="errormessage" />
      </a4j:outputPanel>
    </s:decorate>
  </li>
</ui:repeat>

有谁知道我怎么能超越这个?

3 个答案:

答案 0 :(得分:8)

你知道他们为什么不让你设置ID,对吗? JSF接管id创建,因为你在重复的组件循环中,如果他们让你只设置id,你最终会得到重复的ID,这对你无论如何都无济于事。

在不知道您为什么要明确设置ID的情况下,很难为您提供解决方法。如果是JavaScript,你可以做Grant Wagner所建议的,让JSF给你它作为id的内容。您还可以查看生成的HTML并查看id的格式.JSF通常使用

"form_id:loop_id:loop_index:component_id" 

作为为表单/重复中的组件生成的id。您必须确定并为您的表单提供id和ui:重复标记以了解它们是什么。

好的,你回答说你想在循环中为特定的inputText设置一个h:message标签,这很容易。

<h:inputText id="myInput" .... />
<h:message for="myInput" ... />

现在,为输入生成的消息将显示在消息中,而JSF将破坏“for”属性(虽然这不是生成HTML)就像它将是inputText中的“id”属性所以它们匹配。

您甚至可以在处理程序代码中使用OWN消息转到特定的h:消息,但是在给定支持bean(而不是值)的情况下,您需要使用对clientId的调用来获取消息的目标支持有问题的组件。

答案 1 :(得分:3)

我假设您想控制输入组件的ID,以便稍后在Javascript中引用它?

由于您无法通过表达式设置ID,我这样做:

<h:inputText id="whatever" value="..." />

然后在代码中:

<script type="text/javascript">
var theElement = document.getElementById('<h:outputText value="#{pagecode.whateverClientId}"/ >');
...
</script>

在页面代码中:

protected HtmlInputText getWhatever() {
    if (whatever == null) {
        whatever = (HtmlInputText) findComponentInRoot("whatever");
    }
}

public String getWhateverClientId() {
    return getWhatever().getClientId(getFacesContext());
}

希望有所帮助。

答案 2 :(得分:0)

您是否尝试过使用facelets?

这将允许您分配自己的ID,即:

me:labelKeyThingo然后可以使用id =#{labelKey}来制作唯一标签。以下是我的错误代码 m:textPassword 中的一个示例facelet:

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core" xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich">

   <ui:composition>

    <c:set var="styleClass" value="formPrompt" />
    <c:set var="requiredLabel" value="" />
    <c:choose>
        <c:when test="${required=='true'}">

            <c:set var="required" value="true" />
            <c:set var="styleClass" value="formRequiredPrompt" />
            <c:set var="requiredLabel" value="*" />
        </c:when>
    </c:choose>

    <h:panelGroup id="#{id}_formRowTemplateLabel_panelGroup">
        <h:outputLabel for="#{id}" styleClass="#{styleClass}" id="#{id}_formRowTemplate_outPut"
            value="#{label}" />
        <c:if test="${required == 'true'}">
            <h:outputText value="#{requiredLabel}" styleClass="formRequiredPromptAsterix"></h:outputText>
        </c:if>
    </h:panelGroup>

    <h:panelGroup id="#{id}_textPasswordTemplate_panelGroup">
        <h:inputSecret required="${required}" id="#{id}" value="#{property}"
            styleClass="formText">

            <f:validator validatorId="Maserati.Password" />
            <f:validateLength maximum="16" minimum="8" />
            <ui:insert name="additionalTags"></ui:insert>
        </h:inputSecret>

        <h:message styleClass="formErrorMsg" id="#{id}_textPasswordTemplate_msg" for="#{id}" />
    </h:panelGroup>

   </ui:composition>

   </html>

因此使用:

 <m:textPassword id="password" label="#{msgs.passwordPrompt}"
 property="#{individualApplicationMBean.password}"
 required="true" maxlength="16" />