Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Id's in JSF/Seam

Tags:

jsf

seam

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:

<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?

like image 678
Lee Theobald Avatar asked Nov 25 '08 09:11

Lee Theobald


2 Answers

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.

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

"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.

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

<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.

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.

like image 184
billjamesdev Avatar answered Nov 02 '22 13:11

billjamesdev


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

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

<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.

like image 35
Grant Wagner Avatar answered Nov 02 '22 15:11

Grant Wagner