0
votes

I am trying to get an h:textInput to rerender on change, I have tried it with a4j:ajax and f:ajax.

When using a4j:ajax:

<h:panelGroup id="xyzPG">

<ui:repeat var="var" ... >
   ...
  <h:inputText id="#{idController.getIdXYZ(var.id)}" 
   value="#{someModel.value}" 
   size="3" 
   styleClass="#{errorController.getErrorStateStyleId(idController.getIdXYZ())}">
   <a4j:ajax event="change" render="xyzPG" listener="#{listener.doSomeStuff}" />
  </h:inputText> 
  ...
</ui:repeat>  
</h:panelGroup>

This works the first time, after the panel has updated the first time it stops updating the modell and the listener isn't called either. However the render is triggered causing the old values to be displayed.

Now when I replace a4j:ajax with f:ajax I get the error message that the id xyzPG cannot be found within xyzInput.

<f:ajax event="change" render="@this" listener="#{listener.doSomeStuff}" />

When I try limiting the rerender to the inputText it always updates the model and the listener is called, however the h:inputText is not rerendered.

I have already tried placing another panelGroup around the inputText but that didn't work either.

The reason why we are not using h:dataTable is because we have to produce a Table with the following layout:

---------------------------- 
| dataSet1     | dataSet 2 |
----------------------------
| dataSet3     | dataSet 4 |
etc...

Hence we are using the offset and step attributes of ui:repeat.

2
Did you try with other evens like blur,onkeyup etc..?SRy
Your dynamic use of id makes my eyes bleed. You can avoid all the trouble associated with this using something like in this answer: stackoverflow.com/a/7312979/785663 I think you're suffering from a view vs. render time problem. There's no c:repeat - do you have ui:repeat or c:forEach there? If the latter, see also this obligatory linkmabi
wupps - typ mistake - as you rightly point out its ui:repeat thats what happens when you write out code instead of copying the orignal. Regarding the dynamic id - i am not too happy with it either, but due to project specific constraints, the desicion was made by the project architect, so we are stuck with this.dngfng
I have added the explenation as to why we are using ui:repeatdngfng

2 Answers

1
votes
  1. By design, you can't dynamically generate id attributes using a render-time tag like <ui:repeat/>
  • Compile-time V Render-time tags

    For the purposes of view construction and ajax-updates, the ids of components must be available during view construction before a view is rendered. <ui:repeat/> already caters for uniqueness in the ids of it's child components. But if you require control of the ids, you need to use a compile-time tag handler like <c:forEach/>:

      <c:forEach items="#{idController.itemsList}" var="theVar">
         <h:inputText id="#{idController.getIdXYZ(theVar.id)}" value="#{someModel.value}" size="3" styleClass="#{errorController.getErrorStateStyleId(idController.getIdXYZ())}">
             <a4j:ajax event="change" render="xyzPG" listener="#{listener.doSomeStuff}" />
         </h:inputText> 
      <c:forEach/>
    
  1. It's unlikely that you'll be able to reach xyzPG from within the <ui:repeat/> because the <ui:repeat/> is also a naming container, just like <h:panelGrid/> and so forth. The ajax update works with Richfaces because they've made special provisions for such use cases. <f:ajax/> however will not tolerate it. xyzPG is outside the scope of the <ui:repeat/> so to reach that component, you need to use a qualified naming convention:

      <f:ajax event="change" render=":form1:xyzPG" listener="#{listener.doSomeStuff}"/>
    

This assumes that xyzPG is directly contained within an <h:form id="form1"/>

-1
votes

without seeing your backing bean code , I think you should use

<h:inputText id="#{idController.idXYZ}"

instead of

<h:inputText id="#{idController.getIdXYZ()}"