1

I have a problem with submitting composite components.

Most of my composite components contain both the input components and the "submit" button. When I tried to put the button still in the same h:form but not in the same composite component, the submitted value seemed to be "lost" somewhere. And, for instance, my validators got called on original values.

Example :

<composite:interface>
  <composite:attribute name="titreContext" required="true"/>
</composite:interface>
<composite:implementation>

    <p:outputPanel id="selectionTitreDetailsPanel" styleClass="selectionTitreDetails">
    <p:outputPanel id="selectionTitreDetailsPanelInner" rendered="#{not empty cc.attrs.titreContext.selected}">

    <p:panelGrid columns="2" id="panelId">
      <h:outputText id="idLabel" value="Id :"/>
      <h:outputText id="id" value="#{cc.attrs.titreContext.selected.titeluid}"/>
      <p:tooltip for="id" value="Identifiant unique"/>
    </p:panelGrid>

    <p:panelGrid columns="2" id="titelePanel">
        <p:outputLabel for="selectTitele" value="Titre :"/>
        <p:selectOneMenu id="selectTitele" value="#{cc.attrs.titreContext.selected.titele}" effect="fold" styleClass="fullWidth">
            <f:selectItems value="#{constants.getTitelesForTypman(cc.attrs.titreContext.selected.titele.typman)}" var="titele" itemLabel="#{titele.titelelil}" itemValue="#{titele}" styleClass="fullWidth"/>
                <p:column styleClass="fullWidth">#{titele.titelelil}</p:column>
        </p:selectOneMenu>      
    </p:panelGrid>

    [...]
    <p:commandButton id="confirmerModifications" icon="small_edit" type="submit" value="Confirmer les modifications" 
                    action="#{elutersEditionContext.confirmeModifsSelection}" process="mandatsTerritorial" 
                    update="mandatsTerritorial #{cc.attrs.notifUpdates}"/>

</composite:implementation>

works.

But putting the p:commandButton out of the composite :

<h:form>
<mylib:mycomponent /*parameters *//>
<p:commandButton /*parameters*/ />
</h:form>

does not work. When I debug my validators, I can see that the modified values where not even submitted. Neither getLocalValue, getSubmittedValue nor getValue is changed.

Is there a syntax in composite component declaration to use to correct this situation ? By the way : when I was writing my components as composite components rather than custom components, retrieving #{asen} in the backing bean just worked.

Thanks in advance.

I am using :

  • PrimeFaces 3.4.1
  • CODI 1.0.5
  • OpenWebBeans 1.1.6
  • MyFaces 2.1.9
  • Tomcat 7.0.32

(update) This very strange problem was caused by h:form nesting.

Very strange because h:form nesting did not perturbate the processing of the first level of composite components, but caused this strange "input lost" in nested composite.

Nesting looked like this :

<h:form>
...
    <p:tabView ...>
        <p:tab>
        <h:form>
            <my:composite ....>
        </h:form>
    </p:tabView>
</h:form>
Ludovic Pénet
  • 1,136
  • 1
  • 16
  • 32

1 Answers1

2

You're using a relative client ID in the process attribute of the <p:commandButton>:

<p:commandButton ... process="mandatsTerritorial" />

A relative client ID is relative to the parent NamingContainer component. It will be searched as direct child of the NamingContainer component. If the child is by itself a NamingContainer, then its children would not be searched.

Composite components are by itself in fact also NamingContainer components. If the button is placed in the composite, then this will be searched as direct child of the <cc:implementation>. In your particular case, only the component with id="mandatsTerritorial" will be processed on form submit, including all of its children (note that this component is nowhere visible in the code posted so far, but I'd imagine that you omitted it for brevity).

If the button is placed in <h:form>, then this will be searched as direct child of the <h:form>. However as this is apparently been placed inside the composite (which is, as said, another NamingContainer component), it wouldn't be found and hence basically nothing would be processed. You'd need to fix the process to point to the right client ID. E.g.

<h:form>
    <mylib:mycomponent id="mycomponent" />
    <p:commandButton ... process="@this mycomponent:mandatsTerritorial" />
</h:form>

This way it will process itself (mandatory to invoke the action!) and the component with id="mandatsTerritorial" inside the <cc:implementation> of the composite with id="mycomponent".

As a completely different alternative, which would work just fine in this particular construct, is to remove the process attribute altogether. It defaults to @form already which will thus process the entire form.


Update as per your question update: nesting forms is invalid in HTML. Using the JSF <h:form> representation doesn't change that; you'd still end up with nested forms in HTML. The browser behaviour is unspecified as to which data would be submitted to the server. Make sure that you don't nest <h:form> in JSF as well.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I know this isn't how things are done in Stack Overflow but I had no other idea of how I could contact you here. I asked a question on here earlier today but unfortunately it only got 12 views. Maybe it was a bad time of day. But I know you would know the answer to my question and I am really looking for some insight from a professional. If you could take a few seconds to read over my post I would really appreciate it. Thank you sir http://stackoverflow.com/questions/13161747 – gmustudent Nov 01 '12 at 04:53
  • @gmu: I do lately not explicitly look around in JDBC and Tomcat tags anymore (although, sometimes in the weekend only) as there are lately already "enough" JSF/JSP/Servlet questions to answer. – BalusC Nov 01 '12 at 10:50
  • @BalusC : thank you for this reply. My question was not clear enough. I do not use a process="" when putting the commandButton out of the composite. As it did not work, I tried to explicitly set the default value, @ form, for process. And this does not work. At last, you confirm me that it should... :-) – Ludovic Pénet Nov 01 '12 at 13:43
  • Hmm OK, I might need to add that I'm using Mojarra. But if it would after all indeed have been a bug in MyFaces, that would have been an embarrassing one. – BalusC Nov 01 '12 at 13:46
  • I also strongly doubt that this is a bug in myfaces, as it would be a very big one. I will have to investigate further. I hope this is pbkac. :-) – Ludovic Pénet Nov 01 '12 at 13:58
  • Scratching a bit more : input components from the first level of composite component are processed ok. The first level component uses itself a second level component, using a third level component containing other inputs to validate. Those are not properly processed (validator called, but for old values). – Ludovic Pénet Nov 05 '12 at 14:09
  • You're talking about nested composites? Are you sure that you aren't nesting `` as well? (which is namely invalid in HTML). – BalusC Nov 05 '12 at 14:10
  • There are some small nested h:form, but they contain parts of the components not implied there. I removed them and the problem is still the same. – Ludovic Pénet Nov 05 '12 at 14:56
  • Well, one more time, @BalusC was just *right*. For a reason I do not know, it just messed with nested-nested-nested tag component or nested component because I was using a h:form in a tab of a primefaces tabView, itself in a h:form. BalusC : should I edit the question to mention the real cause of the problem ? Thanks a lot for your very useful help and kind attention. – Ludovic Pénet Nov 05 '12 at 15:42
  • You're welcome. I added an update to the answer which should cover that. – BalusC Nov 05 '12 at 16:59