I have a form in my page which has a panel grid inside of it, to show different info. One of the first rows is a breadcrum that shows a tail of selected items at a current moment. I want to define an ajax event for selecting an item and updating that breadcrum (and other components of my page as well). The problem is that I get a "Unable to attach to non-ClientBehaviorHolder parent" error. I searched that this is because PanelGrid Columns (which is the parent component of that breadcrum) doesn't support ajax events, the suggestion was to implement a Data Table, the problem is that i have lots of different components such as Menus, SelectOneMenu, Command Buttons, Graphic Images, etc. that wont render in a DataTable. Is there a way to do this? Here's part of my code as a sample...
<h:form id="catPage">
<p:panelGrid style="width: 100%; margin:auto; text-align: center;">
<!-- Breadcrum of current caregory -->
<p:row>
<p:column colspan="4">
<p:breadCrumb id="breadcrumcat" model="#{categoryBean.dislpayBreadCrumb()}">
<p:ajax event="itemSelect" listener="#{categoryBean.selectCatListener}" update="breadcrumcat" />
</p:breadCrumb>
</p:column>
</p:row>
<!-- More code... -->
</p:panelGrid>
</h:form>
Related
I have a form with a PrimeFaces selectOneMenu which, when the user selects an option, I want to refresh a DataTable in the same form with different data. When I select an option I get a Javascript popup that says "malformedXML: During update: outerTab:j_idt185 not found" with no DataTable refresh and on inspecting the source I see an invisible iframe at the bottom of the page with id="JSFFrameId" that contains an element <partial-response> that in turn contains an element <update id="outerTab:j_idt185" ...> and this contains an element <![CDATA[<div id="outerTab:j_idt185" class="ui-messages ui-widget" aria-live="polite"></div>]]>. I think this references my <messages> tag, but nothing in the backing bean creates a message, and I do see an element in the page source <div id="outerTab:facilitatorTestsForm:j_idt113" class="ui-messages ui-widget" aria-live="polite"></div> where the messages should be, so the messages tag is indeed rendered. I can find no element with an ID containing "j_idt185" and apparently neither can some Javascript.
The "outerTab" in the IDs is a PrimeFaces TabView that contains all this stuff.
A page refresh causes the update to happen and the DataTable shows the correct data for the selected SelectOneMenu option.
I have found several posts by balusC where some element that is updated by an ajax call has a rendered value that makes it not render and therefore unable to be found when the update is called for. The target of my update (the DataTable) has no rendered attribute and is visible all the time, so this is a different problem. Other posts speak to a bug in earlier versions of PrimeFaces (I am using 6.1). I cannot figure out why this error occurs.
#Kukeltje kindly pointed me to several posts showing that using an encoding type of multipart/form-data in a file-upload component or a form submit can cause this problem but my page has neither of these.
Here is an excerpt of my page:
<div align="center">
<h:form id="facilitatorTestsForm">
<p:messages for="testBeanMessages" showSummary="true" showDetail="true" globalOnly="true" escape="false" autoUpdate="true" />
Tests for which event?
<p:selectOneMenu value="#{testBean.selectedEventId}" style="top: 7px; ">
<f:selectItem itemLabel="All Tests" itemValue="" />
<f:selectItems value="#{testBean.facilitatorEvents}" var="event" itemValue="#{event.id}" itemLabel="#{event.name}" />
<f:ajax update="facilitatorTests" />
</p:selectOneMenu>
<p:commandButton value="Add a New Test" style="margin: 20px;" oncomplete="PF('newTestDialog').show();" actionListener="#{testBean.createEmptyNewTest}" immediate="true" />
<p:dataTable var="test" value="#{testBean.testsForFacilitator}" rowIndexVar="index" id="facilitatorTests" widgetVar="facilitatorTests" selectionMode="single" selection="#{testBean.selectedTest}" rowKey="#{test.id}">
<p:ajax event="rowSelect" oncomplete="PF('facilitatorEditTestDialog').show(); " update="#form:facilitatorEditTestDialog" />
<p:column>#{index + 1}</p:column>
<p:column headerText="Test" sortBy="#{test.name}" width="40%"><h:outputText value="#{test.name}" /></p:column>
<p:column headerText="Tester" sortBy="#{test.tester.fullname}"><h:outputText value="#{test.tester.fullname}" /></p:column>
<p:column headerText="Manager" sortBy="#{test.manager.fullname}"><h:outputText value="#{test.manager.fullname}" /></p:column>
<p:column headerText="Event" sortBy="#{test.event.name}"><h:outputText value="#{test.event.name}" /></p:column>
<p:column headerText="Functional Area" sortBy="#{test.functionalArea.name}"><h:outputText value="#{test.functionalArea.name}" /></p:column>
<p:column headerText="Complete" width="150" sortBy="#{test.completionDate}"><h:outputText value="#{test.completionDate == null ? 'Not Completed' : test.completionDate}"><f:convertDateTime pattern="M/d/yyyy hh:mm a" /></h:outputText></p:column>
<p:column id="delete" style="text-align: center; vertical-align: middle; min-width: 54px; ">
<p:commandButton update="facilitatorTests" process="facilitatorTests" icon="ui-icon-close" actionListener="#{testBean.deleteTest(test.id)}"
title="If the test has not been completed, it will be deleted permanently. Otherwise it will be archived."/>
</p:column>
</p:dataTable>
<... a few dialogs with conditional rendering ...>
</h:form>
</div>
I have tried different targets for the selectOneMenu update attribute and it does not change the behavior so I believe it is correct.
Primefaces 6.1
Mojarra JSF API & IMPL 2.2.4
EL 3.0.0
Tomcat 7
Is this a JSF bug? Thanks for any help you can offer.
Found the solution. Thanks to #Kukeltje for staying with me through this even if he did downvote my question for not having enough info :)
It comes back to #BalusC's posts about not rendering the target of an ajax update. In this case I had several PrimeFaces TabView tabs containing <p:messages> tags with autoUpdate="true", and the tabs are shown/hidden depending on the role of the user. When I removed autoUpdate="true" from these messages tags the problem went away. Apparently every time I did an ajax post, even if I had partial submit limited to rendered subelements of the current visible tab, autoUpdate causes JSF to try to update the messages tags in the unrendered tabs and of course they cannot be found.
The way I found this was to put id attributes EVERYWHERE, on every element in my forms. Then the Javascript error pointed me to a named (id'd) element, rather than one with an automatically assigned ID that I could not trace, and when I saw "autoUpdate" the light bulb came on. Moral: put ids on EVERYTHING.
I hope this helps someone with the same symptom to look for autoUpdate everywhere.
And #Kukeltje you were right that my post had inadequate information - without the enclosing tab tags with their rendered attributes you could not have seen the problem. Since they were in another template that ui:includes the forms I did not think they were relevant. Wrongo!
I have created a JSF application using Myfaces 2.1.12 and Richfaces 4.3.3. On normal browsers the application works fine, but the client insists that he also needs to use a "browser" - IE8, version 8.0.7601. I am having a bunch of problems.
I have a rich:extendedDataTable on the main form. Clicking a row is to open a popup with the details (that is rendered and filled with the data from the selected row). The popup can also be called from a toolbar, this way it displays the details of the row that was selected when the page was first loaded.
The table is defined as follows (column definition removed for clarity)
<h:form>
<rich:extendedDataTable id="table" rowClass="row" rows="15"
value="#{scheduleController.allSchedules}" var="schedule" selectionMode="single"
selection="#{scheduleListBean.selectedSchedule.selection}" clientRows="15">
<a4j:ajax render="scheduleDetails, toolbar, transferListPopup" event="selectionchange"
listener="#{scheduleController.scheduleSelectionChanged}"
oncomplete="#{rich:component('scheduleDetailsPopup')}.show()"/>
...
</rich:extendedDataTable>
</h:form>
The popup contains a couple of panel grids, one of wich contains some buttons.
<h:panelGrid columns="2" styleClass="alignTop" id="scheduleDetails">
...
<rich:panel header="#{generalProperties.controls}">
<h:panelGrid columns="4">
<a4j:commandLink styleClass="btn" type="button"
render="table#body, transferDetailsPanel, destinationPanel, datesPanel"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('scheduleDetailsPopup')}.hide()"
status="pleaseWait" action="#{scheduleController.saveSchedule}"
value="#{generalProperties.save}" />
<h:commandButton class="btn" action="#{scheduleController.changeScheduleStatus}"
value="#{applicationProperties.changeStatus}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="changeScheduleStatusPopup" operation="show" />
</h:commandButton>
<h:commandButton class="btn" value="#{generalProperties.delete}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="removeSchedulePopup" operation="show" />
</h:commandButton>
<a4j:commandButton styleClass="btn" type="button"
render="fileTable, transferDetailsPanel, destinationPanel, datesPanel"
disabled="#{scheduleController.currentSchedule.id == null}"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('transferListPopup')}.show()"
status="pleaseWait" value="#{applicationProperties.transferHistory}" />
</h:panelGrid>
</rich:panel>
</h:panelGrid>
The disabled="#{scheduleController.currentSchedule.id == null}" part checks the bean if anything is selected as the popup is also used to add new rows.
Everything works fine on firefox. On IE8:
clicking the commandLink does not work(nothing happens, besides a "#"
that is appended to the url in the browser) when the popup is called from the
extended data table (rendered), but works when it is called from the
toolbar.
clicking the commandButton does not work(page is reloaded instead of an ajax request beeing executed) when the popup is called from the extended data table (rendered), but works when it is called from the
toolbar.
if I remove the type="button" from command buttons, then clicking them causes the entire page to be reloaded
What am I missing?
The answer was in the question itself. I rebuilt the UI so that no buttons are rendered in ajax requests. This way it works both on IE 8 and IE 9.
Ie.: Instead of setting the disabled attribute based on a bean and rendering the buttons I had to use two instances of each of those buttons. I did that by extracting a form into a composite component using composite:insertChildren just to inject buttons in the proper state and having two instances of the form on the page, showing the right one when the user clicked new schedule / edit schedule.
The drawback of this method is that I had to set the render attribute of the components that show the popup to something different then forms (in this case - panels), which would be an issue if I used Mojarra (see this question: javax.faces.ViewState is missing after ajax render)
I'm using JSF with PrimeFaces to make an application as an assignment for college. I'm struggling to get something working. I'm using PrimeFaces and I have a tabview which contains 5 tabs. In one of those tabs I have a dataTable which has several rows and columns. This all works fine, but the problem is that I want to submit the form without rerendering the (entire page). The thing is, every column in the dataTable has a selectBooleanCheckbox, and when that checkbox is selected, a button should disappear. If it's unselected the button should appear. This works fine with onchange="this.form.submit()" or onclick="this.form.submit()" but it refreshes the entire application, and it causes the first tab to be selected, rather than the one I was at. So I'm looking for a solution to be able to submit and re-render some stuff without refreshing the entire program. This is my code:
<body>
<h:form id="customerForm">
<p:dataTable id="customerlist" var="c" value="#{customerBean.customerList}">
<p:column>
<f:facet name="header">Select</f:facet>
<center>
<p:selectBooleanCheckbox value="#{c.selected}" onchange="this.form.submit()"/>
</center>
</p:column>
</p:dataTable>
<h:commandButton id="testtest" value="test" rendered="#{customerBean.numberSelected() == 0}"/>
</h:form>
</body>
I removed most of the columns for the sake of simplicity. What is the solution to this? I've tried using ajax, but that didn't work
<p:selectBooleanCheckbox value="#{c.selected}">
<f:ajax event="click" execute="#form" render="#none"/>
</p:selectBooleanCheckbox>
Do you really need to submit the whole form? If it's enough that the view is being rerenderd try just to update the form. For that you can use the primefaces ajax event.
<p:selectBooleanCheckbox value="#{c.selected}">
<p:ajax update="#form"/>
</p:selectBooleanCheckbox>
If this does not work, please tell us what "..ajax, didn't work" exactly mean. Is there any POST Request submitted? Is any Action/Setter called?
I have noticed that pretty much all PF components that have 'dynamic' attribute set to 'true' will only show up after a short delay (which is understandable), and also will not trigger ajax start/stop event.
This is my (perfectly working) Ajax status component, actual dialog contents omitted for brevity:
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();" onerror="errorDialog.show();"/>
This is a dynamically loaded dialog. It needs to get data from backing beans:
<p:dialog modal="true" widgetVar="confDialog" position="center" id="confD" dynamic="true">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="Date"></h:outputText>
</p:column>
<p:column>
<h:outputText value="#{myBean.currentDate}">
<f:convertDateTime locale="#{myBean.currentLanguage}" type="both" dateStyle="full" timeStyle="full" timeZone="#{myBean.currentTimeZone}"></f:convertDateTime>
</h:outputText>
</p:column>
</p:row>
</p:panelGrid>
<p:commandButton value="Close" type="button" onclick="confDialog.hide();">
</p:commandButton>
</p:dialog>
A commandbutton that does something and displays dynamically loaded confirmation dialog:
<p:commandButton value="Do it" type="submit" ajax="true" process="#form"
action="#{bean.processForm}"
oncomplete="if(!args.validationFailed){confDialog.show();}"
update="confD #form"/>
Ajax status dialog is displayed while the commandbutton submits the data to backing bean and gets data back. Then ajax status dialog disappears, there is a delay of 1-2 seconds, and confirmation dialog is shown.
The same happens with dynamically loaded tabs (in PF tabView component).
Why isn't my ajax status dialog displayed during dynamic component load? How can I show it?
EDIT:
thanks to #partlov I figured out a solution without overriding PF function, by adding JQ ajax start/stop handler to the dynamically loaded dialog:
jQuery(document).ready(function() {
confDialog.getJQ().ajaxStart(function(){statusDialog.show()});
confDialog.getJQ().ajaxStop(function(){statusDialog.hide()});
});
As written in Primefaces documentation <p:ajaxStatus> just intercepts global AJAX requests, and this request is not global. There is no easy way to do this what you want. As time of loading of dialog is short I really don't see point for this. Only solution, as I think, is to overload Primefaces dialog JavaScript methods.
Primefaces calls loadContents() method when dialog content is loaded so you can override this method for this. I don't advice you to do that, because this is undocumented and can be changed in future versions of Primefaces:
jQuery(document).ready(function() {
var oldLoadContents = PrimeFaces.widget.Dialog.loadContents;
PrimeFaces.widget.Dialog.loadContents = function() {
statusDialog.show();
oldLoadContents();
}
});
This should show your dialog on dynamic loading. You can use onShow attribute of p:dialog to close your dialog:
onShow="statusDialog.hide()"
I am trying to create a datatable that displays a blockUI whenever it is busy, and I have been mostly successful. It now grays out and shows "Loading..." whenever I click either of two commandButtons, sort the datatable by clicking on a header, or page through the datatable. You can see the code for it below.
The problem is that after I have used one of the commandButtons (which runs an ajax update on the blocked element), subsequent actions do not trigger the blockUI (until I refresh the page). For example:
Load page
Click a datatable header - blockUI appears until table is finished sorting
Click one of the datatable page navigation buttons - blockUI appears until the page is loaded
Click one of the commandButtons - blockUI appears until the button's actionListener has finished
Click a datatable header - table sorts, but blockUI does not appear.
Click one of the datatable page navigation buttons - page loads, but blockUI does not appear
Click one of the commandButtons - actionListener runs and table updates, but blockUI does not appear
Reload the page - everything works properly again
Changing the commandButtons' update="" attribute to ajax="false" causes the sorting/paging to always display the blockUI, but the commandButtons to never display the blockUI.
Any ideas?
<div class="buttonDiv">
<p:commandButton ... update="resultsPanel" id="submitButton" ... />
...
<p:commandButton ... update="resultsPanel" id="resetScenarioButton" ... />
</div>
<p:panel header="Results Grid" id="resultsPanel">
...
<p:dataTable ... id="VAResults" ... >
...
</p:dataTable>
....
</p:panel>
<p:blockUI block="resultsPanel" trigger="submitButton, resetScenarioButton, VAResults">
Loading...
</p:blockUI>
The trigger attribute binds jQuery listeners on the specified elements. However if you update an element the binding gets lost. I don't know if it works, but you could try moving the <p:blockUI inside the resultsPanel. I suspect that when you update the panel the blockUI gets updated too and thus re-binding the listener to the data table.
<p:panel header="Results Grid" id="resultsPanel">
...
<p:dataTable ... id="VAResults" ... >
...
</p:dataTable>
....
<p:blockUI block="resultsPanel" trigger="submitButton, resetScenarioButton, VAResults">
Loading...
</p:blockUI>
</p:panel>
I've had the same problem and kind of simillar scenario:
<p:dataTable>
....
<p:ajax event="rowSelect" update="buttons" global="false" onstart="blockMessageButtons.show();" oncomplete="blockMessageButtons.hide();"/>
</p:dataTable>
<p:outputPanel layout="block" id="buttons">
<!-- content to be blocked -->
</p:outputPanel>
<p:blockUI block="buttons" widgetVar="blockMessageButtons"/>
The problem was that panel buttons was both updated by ajax, and blocked by blockUI. I had to divide it in two:
<p:dataTable>
....
<p:ajax event="rowSelect" update="buttons-content" global="false" onstart="blockMessageButtons.show();" oncomplete="blockMessageButtons.hide();"/>
</p:dataTable>
<p:outputPanel layout="block" id="buttons-container">
<p:outputPanel layout="block" id="buttons-content">
<!-- content to be blocked -->
</p:outputPanel>
</p:outputPanel>
<p:blockUI block="buttons-container" widgetVar="blockMessageButtons"/>
#siebz0r already provided the explanation why blockUI stops working when a component is updated.
I am using a one blockUI element in the template for all other pages and thus don't want to include more blockUI elements.
If the blockUI element is updated as well one does not need to move the blockUI inside the component that will be updated.
Here is an example:
<p:panel id="surroundingPanel">
...
<p:commandButton value="ButtonName" styleClass="blockUi"
action="actionToBeExecuted" update=":surroundingPanel :blockUiBinding" />
</p:panel>
<p:outputPanel id="blockUiBinding">
<p:blockUI block=":elementToBeBlocked" trigger="#(.blockUi)">
Loading ...
</p:blockUI>
</p:outputPanel>
The element blockUiBinding can be located anywhere, as long as it can be updated. It is wrapping the blockUI element, because blockUI generates at least two different divs. So when the wrapping element is updated also the blockUI will be updated.