How to use p:ajax to update several components in order - ajax

I'm trying to render the following JSF page:
<h:form id="form" prependId="false">
<h:panelGrid width="100%">
<h:panelGroup id="tableDiv" layout="block">
<h:panelGroup layout="block" style="text-align: center;">
<p:dataTable id="table" var="_item"
value="#{primeBean.findTableModel()}">
...
</p:dataTable>
</h:panelGroup>
</h:panelGroup>
<h:panelGrid columns="2" width="100%">
<h:panelGroup id="barChartDiv" layout="block">
<p:barChart id="barChart"
value="#{primeBean.findCartesianModel()}">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="pieChartDiv,tableDiv" />
</p:barChart>
</h:panelGroup>
<h:panelGroup id="pieChartDiv" layout="block">
<h:panelGroup layout="block">
<p:pieChart id="pieChart">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="tableDiv" />
</p:pieChart>
</h:panelGroup>
</h:panelGroup>
</h:panelGrid>
</h:panelGrid>
</h:form>
When I click in any bar on p:barChart, I expect that the components in the update attribute would be rendered in the order that I declare (pieChartDiv,tableDiv), but they are rendered in reverse order (tableDiv,pieChartDiv).
Is this normal behavior? How can I update a component list in the order the items are declared?

That's not possible this way. The components are searched and updated in exactly the same order as they appear in the JSF component tree.
One way would be to rearrange/swap the both components in the tree hierarchy and reposition them visually with help of CSS. This is however rather clumsy.
Another way would be to update the 2nd component on complete of the update of the 1st component (and thus effectively end up with 2 ajax requests instead of 1). You can achieve that with help of <p:remoteCommand> which is invoked on complete of the <p:ajax>.
So, instead of
<p:ajax ... update="pieChartDiv,tableDiv" />
use
<p:ajax ... update="pieChartDiv" oncomplete="updateTableDiv()" />
...
<p:remoteCommand name="updateTableDiv" update="tableDiv" />

Not so elegant but working solution can be this:
<p:barChart id="barChart"
value="#{primeBean.findCartesianModel()}">
<p:ajax event="itemSelect" listener="#{primeBean.handleItemSelect}"
update="pieChartDiv" /> <!-- This will be updated as first. -->
<p:ajax event="itemSelect"
update="tableDiv" /> <!-- And this will be updated as second. -->
</p:barChart>

Related

Values repeated in jsf <ui:repeat>

I have repeated values on my form. I am using <ui:repeat> tag.
My code:
<h:panelGroup id="alvs">
<ui:repeat value="#{encuestaController.newEncuesta.preguntas}" var="preg">
<h:outputLabel for="preg" value="add question:" style="font-weight:blue" />
<p:inputText id="preg" value="#{preg.pregunta}" />
<h:outputLabel for="value2" value="The question is option:" style="font-weight:bold" />
<p:selectBooleanButton id="value2" value="#{preg.opcional}" onLabel="Si" offLabel="No" onIcon="ui-icon-check" offIcon="ui-icon-close" style="width:60px">
<p:ajax update="f1:growl2"/>
</p:selectBooleanButton>
<h3 style="margin-top:2px">Question Type</h3>
<p:selectOneMenu value="#{preg.tipo}">
<f:selectItem itemValue="1" itemLabel="one option" />
<f:selectItem itemValue="2" itemLabel="many option" />
</p:selectOneMenu>
<h:panelGroup id="aux">
<ui:repeat value="#{preguntaController.newPregunta.opciones}" var="opc">
<h:panelGroup id="pn11" rendered="#{preg.tipo eq 1}">
uno<p:inputText value="#{opc.descripcion}"/>
</h:panelGroup>
<h:panelGroup id="pn12" rendered="#{preg.tipo eq 2}" >
dos<p:inputText value="#{opc.descripcion}"/>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
<p:commandButton class="btn-floating btn-large waves-effect waves-light red" actionListener="#{preguntaController.addOcion}" update="f1:growl2" value="Add" >
<f:ajax execute="pn11 pn12" render="alvs" />
</p:commandButton>
The problem is when I want to add a new option(opciones) in the question(pregunta) with <p:commandButton/>
This adds the same options for the previous question as for the new one.
Maybe, the error is ajax? <f:ajax execute="pn11 pn12" render="alvs" />
Help me!!!
Image Description
As i see it, the problem is regarding the fact that you are producing multiple options using the ui:repeat, but you are declaring the same id for each of the panelGroups inside.
Add some custom prefix or sufix to each of the ids based on some unique value from the var="opt" (like an id):
<ui:repeat value="#{preguntaController.newPregunta.opciones}" var="opc">
<h:panelGroup id="pn11#{opc.id}" rendered="#{preg.tipo eq 1}">
uno<p:inputText value="#{opc.descripcion}"/>
</h:panelGroup>
<h:panelGroup id="pn12#{opc.id}" rendered="#{preg.tipo eq 2}" >
dos<p:inputText value="#{opc.descripcion}"/>
</h:panelGroup>
</ui:repeat>
Otherwise you will keep overriding the previous panelGroup's.
Also you would need to use a broader scope of execution for your ajax request.
I would use the first panelGroup outside of the ui:repeat:
<f:ajax execute="aux" render="alvs" />

Parts which are ajax-rendered after actions doesn't work fine unless you reload the page

The fist time I go to the JSF page and I make an action for rendering some parts of the page, those parts are not rendering anymore. However, if you reload the page, thats areas are rendering fine.
For me, it seems that first time the page is constructed the ids are not prepended correctly. That causes the Jboss server to ignore every posted value because it cannot find a concurrent element in the site.
Reloading the page solves the problem with the false prepending of the ids.
I don't know because this, someone got the same problem? I have tried to solve it, but I was impossible.
Here you have the code:
<h:form id="select" styleClass="applic_filterside" binding="#{companyOverview2.selectForm}">
<a4j:region>
<h:panelGroup layout="block" styleClass="applic_filter_selectrow">
<tibuga:selectManyCheckbox label="Branche:" valueBean="#{companyOverview2}" valueProperty="selectedSectorID"
id="selSec" items="#{generalData.allSectors}" itemValue="#{c.id}" var="c" itemLabel="#{c.name}" width="174"
showButtonsSelectAll="false" display="none">
<a4j:ajax event="click" onbegin="submitSearch();"></a4j:ajax>
</tibuga:selectManyCheckbox>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="applic_filter_selectrow">
<a4j:commandLink action="#{companyOverview2.filterSearchEntrys()}" onclick="flushInputs(this);" oncomplete="turnInputs(document.getElementById('select:button'));"
render="companyTableNew" execute="#form" limitRender="true" id="button">
<h:graphicImage value="/resources/images/fields/filter.png" />
</a4j:commandLink>
</h:panelGroup>
</a4j:region>
</h:form>
<h:panelGroup id="companyTableNew" >
<h:form>
<h:panelGroup layout="block" styleClass="applic_filter_countrow">
<h:outputText value="Treffer: #{companyOverview2.count()} Unternehmen" />
</h:panelGroup>
<a4j:region>
<h:panelGroup layout="block" id="cont" styleClass="applic_applicants">
<h:panelGroup layout="block" styleClass="top_line">
<h:panelGroup layout="block" styleClass="sectors">
<h:outputText value="Branche" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="location">
<h:outputText value="Standort" />
</h:panelGroup>
<h:panelGroup layout="block" styleClass="size">
<h:outputText value="Größe" />
</h:panelGroup>
</h:panelGroup>
<ui:repeat value="#{companyOverview2.filteredCompanysNew}" var="a">
<tibuga:singleCompanyEntry entry="#{a}" />
</ui:repeat>
<h:panelGroup layout="block" styleClass="companys_actions">
<a4j:commandLink value="weitere Unternehmen anzeigen ..." action="#{companyOverview2.showMore()}" render="companyTableNew" rendered = "#{companyOverview2.showMoreLink}"/>
</h:panelGroup>
</h:panelGroup>
</a4j:region>
</h:form>
</h:panelGroup>
The problem is that the first time that you go to the page, you can see the results correctly, but if you make a query the datas from CompanyTableNew are wrong, but reloading the page all is right.

Primefaces update from inside another form

I'm not sure what's wrong with my HTML code. From what I read, it should work. I even tried using prependId="false" which didn't resolve the problem of not finding the UI Component.
<p:tabView>
<p:tab title="Tab1" id="tab1">
<h:form id="form1" prependId="false">
<p:panelGrid columns="2" id="grid1">
<h:outputLabel for="minDraw" value="Starting draw number:" />
<p:inputText id="minDraw" value="#{LottoMaxBacking.minDraw}" />
<p:commandButton value="Get Frequency From Begining"
actionListener="#{LottoMaxBacking.loadAllDrawFreq}"
update=":form2:freqTable" />
</p:panelGrid>
</h:form>
<h:form id="form2" prependId="false">
<p:dataTable var="entry" value="#{LottoMaxBacking.drawFreqList}"
id="freqTable">
<f:facet name="header">
<h:outputText value="#{LottoMaxBacking.tableHeader}" />
</f:facet>
<p:column sortBy="#{entry.key}" headerText="Ball Number">
<h:outputText value="#{entry.key}" />
</p:column>
<p:column sortBy="#{entry.value}" headerText="Frequency">
<h:outputText value="#{entry.value}" />
</p:column>
</p:dataTable>
</h:form>
</p:tab>
<p:tab title="Tab 2"></p:tab>
</p:tabView>
I tried ":tab1:form2:freqTable", ":freqTable", and "freqTable" but none of them work. When I put both forms together as a single form, it would find the freqTable fine.
OK I finally figured it out after looking at the error message again.
Cannot find component with identifier ":form2:freqTable" referenced from "j_idt54:j_idt56"
idt54 refers to the TabView and idt56 refers to the command button. So it turns out that my button's AJAX update string didn't go far enough original and all my other attempts referred to the wrong parent container. I added an id to p:tabView and changed the update String and it worked.
<p:commandButton value="Get Frequency From Begining"
actionListener="#{LottoMaxBacking.loadAllDrawFreq}"
update="tv:form2:freqTable" />

a4j commandlink not working after rerender

The text with id=txt is inserted outside the commandlink after rerendering.
And therefore the link is broken. A refresh of the page gets it back.
Could somebody please help?
<h:form id="frm">
<h:selectOneMenu value="#{myBean.currentId}">
<f:selectItems value="#{myBean.selectListA}" />
<a4j:support event="onchange" action="#{myBean.changeSomething}"
reRender="priceGroup,idLink" />
</h:selectOneMenu>
<h:panelGroup id="priceGroup">
<a4j:commandLink id="idLink">
<h:outputText id="txt" value="#{myBean.someValue}" />
</a4j:commandLink>
</h:panelGroup>
</h:form>

Ajax not working with primefaces

In my JSF page I have form when I click submit button in the same page I need to show an static content. But When I click <p:commandbutton> nothing appears in the page. When I put ajax="false" then only action taken place but the Static content display in new page.
In my Backing bean I have used Session scoped. I am using JSF 2.0 and Primefaces 3.2.
My JSF Page.
<h:form>
<h:panelGroup rendered="#{not license.showForm}">
<p:panel header="License Key Request" >
<h:panelGrid columns="2" >
..
<h:outputText value="Bla bla"/>
..
<h:outputText value="Bla Bla" />
</h:panelGrid>
<TABLE>
..
<h:outputLabel for="name" value="Requestor Name : *" />
..
<p:inputText id="name" value="#{license.name}" required="true" requiredMessage="Name is required."/>
..
<h:outputLabel for="company" value="Company : * " />
..
<p:inputText id="company" value="#{license.company}" required="true" requiredMessage="Company is required."/>
..
</table>
<p:commandButton value="Form" id="btnAdd" process="#form"
action="#{license.add}" />
..
</table>
</p:panel>
</h:panelGroup>
<h:panelGroup rendered="#{license.showForm}" >
<h:outputText value="Bla Bla"/>
</h:panelGroup>
</h:form>
Your source code is somewhat confusing (e.g. you have two closing table tags). But I assume that you want to show the panelGroup at the bottom if the button is clicked.
The easiest way would be to add an update ="#form" to your commandButton:
<p:commandButton value="Form" id="btnAdd"
process="#form" update="#form"
action="#{license.add}" />
You don't need to update the whole form but only the specific component. Then you need to give the panelGroup an id attribute and use this attribute instead of #form. However, since it is not clear for me how your naming containers are organized, it could be puzzling to find the correct relative id.

Resources