Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using validator with a variable attribute in ui:repeat

I'm using com.sun.faces version 2.1.18. In my application I have a dynamic list of questions. I use <ui:repeat> to render each question. Depending on the type of question I render a type of input component and validation. In case of a number range question I use <h:inputText> with <f:validateLongRange>.

The problem I run into is that the minimum and maximum attributes on the <f:validateLongRange> are always set to the first question's minimum and maximum value. So, when you use the validator on any other then the first question it fails. Is that supposed to happen? Is there a way to get validation working on dynamically generated components? I hope it can be solved without switching to <c:forEach>.

Code snippet:

<ui:repeat value="#{questionnaire.questionsCollection}"
           var="question">
  ..
  <h:inputText value="..">
    <f:validateLongRange minimum="#{question.minimumValue}"
                         maximum="#{question.maximumValue}"/>
  </h:inputText>
  ..
</ui:repeat>

I've outputted #{question.minimumValue} and #{question.maximumValue}, and they have the correct values for my question.

like image 837
Jasper de Vries Avatar asked Mar 28 '13 12:03

Jasper de Vries


1 Answers

This is indeed specified/expected behavior. The attributes of taghandlers like <f:validateXxx> are evaluated during view build time. So they can't refer a variable which is only available during view render time like the currently iterated variable of <ui:repeat>. It would indeed work when you use an iterator which runs during view build time like JSTL <c:forEach>. A more elaborate explanation about view build time versus view render time is given here: JSTL in JSF2 Facelets... makes sense?

You have basically the same problem as explained in detail here: How to set converter properties for each row of a datatable? It outlines various solutions in detail. One of the solutions in your particular case would be using OmniFaces <o:validator> which enables render-time evaluation of all attributes, so that you can just replace

<f:validateLongRange minimum="#{question.minimumValue}"
                     maximum="#{question.maximumValue}" />

by

<o:validator validatorId="javax.faces.LongRange" 
             minimum="#{question.minimumValue}"
             maximum="#{question.maximumValue}" />

in order to get it to work as desired.

See also:

  • Setting a validator attribute using EL based on ui:repeat var
like image 80
BalusC Avatar answered Sep 20 '22 21:09

BalusC