JSF / Seam中的动态ID

时间:2021-11-04 20:00:30

Got a little problem with a Seam application I'm working on and I was wondering if anyone knows a way round it. I've got a form in my application that uses AJAX to show certain input boxes depending on an item in a dropdown box. The code works fine except for setting the ID's in my input boxes. It looks like JSF doesn't let me set an ID via a variable. Other attributes like "for" in labels are fine. Here's some code explaining what I mean:

我正在研究的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>

Does anyone have any idea how I can get past this?

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

3 个解决方案

#1


8  

You see why they don't let you set the ID, right? JSF takes over id creation because you're in a repeated loop of components and, if they let you just set the id, you'd end up with duplicate IDs, which wouldn't help you anyway.

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

Without knowing WHY you want to set the ID explicitly, it's hard to give you a workaround. If it's for JavaScript, you can do what Grant Wagner suggests, and let JSF give you what it put as the id. You can also take a peek at the generated HTML and see what format the id is in. JSF usually uses

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

"form_id:loop_id:loop_index:component_id" 

as the id it generates for components in a form/repeat. You'd have to be sure and give id's to your form and ui:repeat tags to know what they were.

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

Ok, you answered that you want to have an h:message tag for a specific inputText inside the loop, that's easy.

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

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

Now, messages generated for the input will be displayed in the message, and JSF will mangle the "for" attribute (though that isn't generated to HTML) just like it will the "id" attribute in the inputText so they match.

现在,为输入生成的消息将显示在消息中,并且JSF将破坏“for”属性(尽管这不是生成HTML),就像inputText中的“id”属性一样,它们匹配。

You can even make your OWN messages in your handler code to go to the specific h:message, but you'll need to use a call to clientId to get the target of the message, given the backing bean (not the value backing bean) of the component in question.

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

#2


3  

I'm assuming you want to control the ID of your input component so you can reference it later in Javascript?

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

Since you can't set the ID via an expression, I do this:

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

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

Then later in the code:

然后在代码中:

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

In the pagecode:

在页面代码中:

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

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

Hope that helps.

希望有所帮助。

#3


0  

Have you tried use facelets?

你尝试过使用facelets吗?

That will allow you to assing your own ids ie:

这将允许你协助自己的ID,即:

me:labelKeyThingo can then use the id=#{labelKey} to make a unique label. Here is an example facelet called m:textPassword from my bad code:

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>

It is used thusly:

因此使用它:

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

#1


8  

You see why they don't let you set the ID, right? JSF takes over id creation because you're in a repeated loop of components and, if they let you just set the id, you'd end up with duplicate IDs, which wouldn't help you anyway.

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

Without knowing WHY you want to set the ID explicitly, it's hard to give you a workaround. If it's for JavaScript, you can do what Grant Wagner suggests, and let JSF give you what it put as the id. You can also take a peek at the generated HTML and see what format the id is in. JSF usually uses

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

"form_id:loop_id:loop_index:component_id" 

as the id it generates for components in a form/repeat. You'd have to be sure and give id's to your form and ui:repeat tags to know what they were.

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

Ok, you answered that you want to have an h:message tag for a specific inputText inside the loop, that's easy.

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

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

Now, messages generated for the input will be displayed in the message, and JSF will mangle the "for" attribute (though that isn't generated to HTML) just like it will the "id" attribute in the inputText so they match.

现在,为输入生成的消息将显示在消息中,并且JSF将破坏“for”属性(尽管这不是生成HTML),就像inputText中的“id”属性一样,它们匹配。

You can even make your OWN messages in your handler code to go to the specific h:message, but you'll need to use a call to clientId to get the target of the message, given the backing bean (not the value backing bean) of the component in question.

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

#2


3  

I'm assuming you want to control the ID of your input component so you can reference it later in Javascript?

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

Since you can't set the ID via an expression, I do this:

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

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

Then later in the code:

然后在代码中:

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

In the pagecode:

在页面代码中:

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

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

Hope that helps.

希望有所帮助。

#3


0  

Have you tried use facelets?

你尝试过使用facelets吗?

That will allow you to assing your own ids ie:

这将允许你协助自己的ID,即:

me:labelKeyThingo can then use the id=#{labelKey} to make a unique label. Here is an example facelet called m:textPassword from my bad code:

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>

It is used thusly:

因此使用它:

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