Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
901 views
in Technique[技术] by (71.8m points)

forms - How to use EL with <ui:repeat var> in id attribute of a JSF component

I have following code:

<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
  <h:form id="#{class2.name}"> 
    <h:outputText value="#{class2.name}" />
  </h:form>
</ui:repeat>

However, when I open the page, it errors as follows:

component identifier must not be a zero-length String

But it is properly printed in the <h:outputText>. How is this caused and how can I solve it?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use EL in the id attribute of a JSF component, but the EL variable has to be available during view build time, while the JSF component tree is to be built. However, the <ui:repeat> runs during view render time, while the HTML output is to be generated based on JSF component tree. The <ui:repeat var> is not available during view build time and #{class2.name} evaluates to null which totally explains the error you got. That it works in <h:outputText> is because it runs during view render time.

If you replace <ui:repeat> by <c:forEach>, which runs during view build time, then it'll work as you intented. The <c:forEach> will namely generate physically multiple <h:form> components in the JSF component tree which each generate individually their own HTML output (in contrary to <ui:repeat>, wherein the very same <h:form> component is been reused multiple times to generate HTML output).

<c:forEach var="class2" items="#{bean.list}" varStatus="status">
  <h:form id="#{class2.name}"> 
    <h:outputText value="#{class2.name}" />
  </h:form>
</c:forEach>

However, I really wonder why you need to do that. There's usually no need to dynamically assign component IDs. JSF will already ensure the uniqueness of the ID. The below example,

<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
  <h:form id="form"> 
    <h:outputText value="#{class2.name}" />
  </h:form>
</ui:repeat>

will end up in multiple forms with each an unique ID, suffixed with iteration index of the <ui:repeat>. If you actually need to use #{class2.name} for some JavaScript/jQuery purposes (you did nowhere state the concrete functional requirement in the question for which you thought that this would be the right solution, so it's merely guessing), then just wrap it in a plain vanilla HTML element:

<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
  <div id="#{class2.name}"> 
    <h:form id="form">
      <h:outputText value="#{class2.name}" />
    </h:form>
  </div>
</ui:repeat>

Or set it as style class of a JSF component, which is also just selectable via a CSS selector:

<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
  <h:form id="form" styleClass="#{class2.name}">
    <h:outputText value="#{class2.name}" />
  </h:form>
</ui:repeat>

See also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...