I got a .xhtml document including two datatables. Each datatable has several ajax events attached to it. The first datatable has a column with link within. If you click on one of them, it opens the second datatable and you can come back to the first one thanks to a button.
The structure looks like this :
Main page :
<html>
<h:body>
// Stuff ...
<div>
// Including first datatable
<ui:fragment rendered="#{GenericReportControllerBean.reportType == 'object'}">
<ui:include src="/site/dialog/uiDatatableGenericReport.xhtml">
<ui:param name="uiGenericBean" value="#{GenericReportControllerBean}"></ui:param>
<ui:param name="rowStyleClass" value=""></ui:param>
</ui:include>
</ui:fragment>
// Including second datatable
<ui:fragment rendered="#{GenericReportControllerBean.reportType == 'family'}" >
<ui:include src="/site/dialog/uiDatatableFamilyReport.xhtml">
<ui:param name="uiGenericBean" value="#{GenericReportControllerBean}"></ui:param>
<ui:param name="rowStyleClass" value="#{object[3] < 0 ? 'red' : ''} #{object[3] > 0 ? 'orange' : ''}"></ui:param>
<ui:param name="subid" value="family"></ui:param>
</ui:include>
</ui:fragment>
</div>
</h:body>
</html>
Datatables have same structure. Headers are the same (which is probably an error cause they share same rows and same ids)
<p:dataTable id="objects#{((subid==null)?'':subid)}"
rows="#{uiGenericBean.rows}" lazy="true"
// others attributes
// Some code...
<p:ajax event="rowSelect" update="objects#{((subid==null)?'':subid)}" />
<p:ajax event="rowUnselect" update="objects#{((subid==null)?'':subid)}" />
<p:ajax event="rowSelectCheckbox" update="objects#{((subid==null)?'':subid)}" />
<p:ajax event="rowUnselectCheckbox" update="objects#{((subid==null)?'':subid)}" />
<p:ajax event="filter" oncomplete="updateFilters()" />
<p:ajax event="toggleSelect" listener="#{uiGenericBean.selectAllObjects}" update="objects#{((subid==null)?'':subid)}" />
</p:dataTable>
My problem is the following : evertyhing is working well until I go into the second datatable. After this, if I go back to the first table and select a row, all rows become selected.
If I remove the ajax events from any datatable, this behaviour stops but my submit button is enabled only if a row is selected. Then without the ajax event and update, my button is never enabled.
I also noticed that, if I remove the update attribute from any table but let the ajax event, the problem persists.
I tried to change the id of both tables but it still does not solve the problem.
I also thought about putting the ajax events in the main page instead, but these tables are used in others pages in the programm.
Any idea why I have this behaviour and how to avoid it ?
I have a scenario where i have a SelectOneMenu
<h:selectOneMenu value="#{bean.names}" valueChangeListener="#{bean.templChangeListner}" required="true" requiredMessage="Please select an Equipment type">
<f:selectItem itemLabel="-------Select Names------"
itemValue="${null}" noSelectionOption="true" />
<f:selectItems value="#{bean.fetchnames()}" var="spec"
itemLabel="#{spec.specName}" itemValue="#{spec.specificationId}" />
<a4j:ajax event="valueChange" render="outputPanel"
immediate="true" execute="#this"/>
</h:selectOneMenu>
On valueChange i have to render a panel which have
<a4j:outputPanel id="outputPanel">
<c:forEach items="#{ban.genericFeaturesList}"
var="genFeatVar" varStatus="genericIndex">
...............
...............
...............
<!--Lots of logic to render component -->
</c:forEach>
My question is that when valueChange will happen and outputPanel will render again
genericFeaturesList will contain new updated data ?
Component tree will be build again ?
As i saw when i am adding redirect in valueChangeListener method then things working properly in UI and when i am removing redirect value in UI not rendering properly.
FacesContext.getCurrentInstance().getExternalContext().redirect("PageName")
JSF can be easily rendered and produce runtime HTML DOM object If we use JSF component instead of <c:forEach...>
<h:panelGroup id="outputPanel" rendered="#{not empty ban.genericFeaturesList}">
<ui:repeat value="#{ban.genericFeaturesList}" var="instance">
......
......
......
</ui:repeat>
<h:panelGroup>
... Try this. Good luck!!!
I hava a composite component with a PrimeFaces dataTable inside. The column definition should be done outside of this component in a facet definition.
<composite:interface>
<composite:attribute name="domains" required="true"/>
<composite:facet name="domainColumns" required="true"/>
</composite:interface>
<composite:implementation>
<p:dataTable var="var" value="#{cc.attrs.domains}">
<composite:renderFacet name="domainColumns"/>
</p:dataTable>
</composite:implementation>
I want to use this component like shown here:
<my:domainTable domains="#{adminTsWorkspaceBean.domains}">
<f:facet name="domainColumns">
<p:column headerText="Header">
<h:outputText value="#{var.id}" />
</p:column>
</f:facet>
</my:domainTable>
Interestingly: If I use the p:column as a child and not as a facet and then in my component <composite:insertChildren/>, I have the desired output. But of course I can insert the children only at one position in my component. I'm trying to define the column for two different dataTables?
I have dashboard with panels:
<p:dashboard id="board" model="#{dashboardOptionsMB.model}">
<c:forEach var="item" items="#{dashboardOptionsMB.emsWidgets}">
<ui:include src="/pages/dashboard/panel.xhtml">
<ui:param name="widget" value="#{item.webDashboardDbBean}" />
<ui:param name="emsValue" value="#{item.emsValue}" />
</ui:include>
</c:forEach>
</p:dashboard>
I load a list dashboardOptionsMB.emsWidgets with content before rendering page, and this works fine with panel component:
panel.xhtml:
<p:panel id="#{widget.widgetid}" header="#{widget.widgetheader}" closable="true" >
<h:outputText value="#{emsValue.value}" />
...
</panel>
So, before each rendering I initialize the list with all elements and content with this method:
DashboardOptionsMB:
private void initWidgets(WebDashboardsDbBean dashboard) {
//dashboard is JPA entity from database
emsWidgets = dashboard.getWidgets();
...
}
What I want to achieve is to load each panel content dynamically after page load. For example each panel should call:
initWidget(String widgetId)
after page load, and when this method is completed to update its content.
Use p:remoteCommand to create some Ajaxified Javascript which will be executed when body is loaded:
<h:body onload="loadWidgets()">
<!-- content -->
<p:remoteCommand name="loadWidgets"
update="#{widget.widgetid}"
actionListener="#{dashboardOptionsMB.initWidgets}"/>
</h:body>
Alternatively, you might use the autoRun="true" argument to have it executed when document is ready:
<p:remoteCommand name="loadWidgets"
update="#{widget.widgetid}"
actionListener="#{dashboardOptionsMB.initWidgets}"
autoRun="true"/>
See also:
JSF lazy loading component value
Make your Primefaces app load faster with lazy loading
I've created an ui:component to use like a popup, so I can create a lot of popups using the standard of this template.
The component is just a popup with two buttons (cancel and submit) and a content that can be overriden, like you can see here:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:component>
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}"
rendered="#{popup.visivel}" visible="#{popup.visivel}"
closeOnEscape="false" closable="false" header="#{titulo}"
resizable="false" styleClass="autoWidthDialog" showEffect="fade"
hideEffect="fade">
<h:panelGroup style="width:100%">
<p:focus />
<ui:insert name="conteudo">Nenhum conteúdo definido!</ui:insert>
<h:panelGrid id="#{idPopup}PainelMensagens" style="width:100%">
<p:messages />
</h:panelGrid>
<ui:insert name="barraDeBotoes">
<h:panelGroup layout="block" style="width:100%">
<p:commandButton value="CANCELAR" immediate="true" update="#form"
style="float:right" action="#{controladorPopup.fechar}"
onclick="#{idPopup}.hide();" />
<p:commandButton value="OK" style="float:right"
update="#form formAlerta"
action="#{controladorPopup.submit}"
process="#form" />
</h:panelGroup>
</ui:insert>
</h:panelGroup>
</p:dialog>
</ui:component>
</html>
The problem happen when I try to submit the form without filling the required fields. The correct behavior is just show again the popup with messages, but the dialog is rendered twice, one with the messages and one without the messages.
You can see this behavior here:
this is one use of this template:
<ui:composition template="../templates/popupSubmit.xhtml">
<ui:param name="titulo" value="Buscar pessoa" />
<ui:param name="popup" value="#{modeloPopupBuscaPessoa}" />
<ui:param name="controladorPopup"
value="#{controladorPopupBuscaPessoa}" />
<ui:define name="conteudo">
<h:panelGroup>
<h:panelGrid columns="2">
<h:outputLabel value="Tipo de cadastro:" style="float:none" />
<h:selectOneMenu value="#{controladorSugestaoPessoa.tipoCadastro}"
immediate="true">
<f:selectItems value="#{carregadorTipoCadastro.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneMenu>
</h:panelGrid>
<h:outputText value="Buscar por:" />
<h:selectOneRadio value="#{controladorSugestaoPessoa.tipoBusca}"
immediate="true">
<f:selectItems value="#{carregadorTipoBuscaPessoa.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneRadio>
<p:autoComplete value="#{modeloPopupBuscaPessoa.itemSelecionado}"
forceSelection="true" maxResults="10" queryDelay="500"
completeMethod="#{controladorSugestaoPessoa.atualizarSugestoes}"
var="pessoa" itemLabel="#{pessoa.label}" itemValue="#{pessoa}"
converter="#{conversorSelectItem}" />
</h:panelGroup>
</ui:define>
</ui:composition>
And these are some use:
<h:form id="cadastroPessoa">
<ui:include
src="resources/components/popups/modulo_cadastro/popupNovoCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupEdicaoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupBuscaPessoa.xhtml">
<ui:param name="idPopup" value="popupBuscaCadastroPessoa" />
</ui:include>
</h:form>
<h:form id="cadastroProduto">
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroProduto.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroProduto" />
</ui:include>
</h:form>
Could someone tell me why this is happening??
I've posted the same question in primefaces forum (like Tommy Chan told), and someone answered this:
You are probably placing your dialog in the form you are updating which is a nono. Never update the dialog only the stuff in the dialog
I've tried to do this until I saw all my dialogs have "rendered" attribute coming from server (just see the first xml), I have a lot of dialogs in this application and some of them have relation with others (on server), these last are on the same form.
I did something different, I only created this javascript code:
function removerDialogo(id) {
setTimeout(function() {
removerDialogoAposIntervalo(id);
}, 100);
}
function removerDialogoAposIntervalo(id) {
id = id.replace(':', '\\:');
jQuery('div.ui-dialog')
.find('#' + id)
.parent().eq(1)
.remove();
}
and called this on dialog "onShow" attribute:
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}" rendered="#{popup.visivel}"
visible="#{popup.visivel}" closeOnEscape="false" closable="false"
header="#{titulo}" resizable="false" styleClass="autoWidthDialog"
showEffect="fade" hideEffect="fade" onShow="removerDialogo(this.id)">
I don't like to do things like this, but I can't find a better way to solve this...
If someone give me a better solution, I will be grateful
In my case I cannot user oncompleteI) method to hide the dialog because it has to be closed to some business logic.
I my case I have use primefaces tabs on UI. Every time I navigate the tabs and then click on button on which dialog appears then my dialogs number are increasing proportionality
So I have used simple jquery script to remove all the duplication dialog from the UI
e UI.
function removeDuplicateDialogs(dialogId) {
\\ generally all our components have : character we have to
\\ replace ':' with '\\:'(applying escape character)
dialogId = dialogId.replace(/\:/g, '\\:');
var dialogs = jQuery("div[id=" + dialogId + "]");
var numOfDialogs = dialogs.length;
numOfDialogs = numOfDialogs - 1;
for (var i = 0; i < numOfDialogs; i++) {
jQuery(dialogs[i]).remove();
}
}
As i said on the primefaces forum, you are updating your forms with the dialog in it... you need to place your dialogs out of your form and update them seperatly. If you need to use a form in your dialog then place it in you dialog:
<p:dialog><p:form> </p:form> </p:dialog>
I had the same problem with a dialog, the solution was place in the update of the commandButton that show the dialog component the specific id of the Dialog Component not the form id, the solution looks like this:
<p:dialog id="dialogId">
<p:commandButton value="OK" style="float:right"
update="#form dialogId"
action="#{controladorPopup.submit}"
process="#form"/>
</p:dialog>
I would check that your widgetVar="#{idPopup}" id="#{idPopup}" is the same before you submit and after you submit the form. Maybe it has changed and primefaces thinks it doesn't exist anymore and creates a new one.
Add the oncomplete attribute to your submit button and let it hide the dialog:
<p:commandButton value="OK" style="float:right"
update="#form formAlerta"
action="#{controladorPopup.submit}"
process="#form"
oncomplete="#{idPopup}.hide();"/>
putting the forms inside dialog isnt the best way to solve it, if you access your application with IExplorer, dialogs wont work with this approach
This is an awful bug with no official answer...
I'm using a dialog to render a Google map. The way I handle the bug (using JQuery) is by counting the number of ".map" elements in the DOM on primefaces:dialog.onShow... I then select the :last .map instance rendered (or in your case, whatever content class you're working with), and .remove() the dialog which contains it:
Markup (approx):
<pri:dialog onShow="popupOpen();" etc...>
<div id="map" class"map"></div>
</pri:dialog>
JavaScript:
function onShowDialog(){
if($(".map").length > 1){
$cull = $(".map:last");
$cull.closest(".ui-dialog").remove();
}
}
If you're a sadist you could, quite comfortably, make that a one liner... I see this as a Primefaces bug. The close button should outright destroy the dialog.