PrimeFaces Composite Components: commandLink doesn't work in dataTable - jsf

'
<cc:implementation>
<p:outputLabel value="#{cc}"/>
<p> <p:commandButton value="Vedi lista file" actionListener="#{cc.researchFileInDirectory}" update="panelFileLog"/></p>
<h:panelGrid id="panelFileLog">
<p:dataTable var="file" rendered="#{cc.viewFileList}" binding="#{cc.listaFile}">
<p:column headerText="File" style="width:100px">
<h:outputText value="#{file.toString()}" />
</p:column>
<p:column headerText="Link" style="width:100px">
<p:commandLink id="downloadLink" value="download" ajax="false" actionListener="cc.downloadFile">
<p:fileDownload value="#{cc.file}" />
</p:commandLink>
</p:column>
</p:dataTable>
</h:panelGrid>
</cc:implementation>'
This component is called in this page
<l:logFile />
It loads the list of files but when I click on commandLink, it does not call the actionListener method but redirects me to the same page.

Every component that uses StreamedContent does not work in a composite component. For more detailed explained, please read http://jsfcorner.blogspot.be/2012/11/advanced-primefaces-graphic-image.html . Since <p:fileDownload/> is one of them you can't use it.

Related

how to reload p:dataGrid programmatically?

I have a datagrid with subscribe and unsubscribe option so the user can subscribe and unsubscribe and vise verse.
now I want to reload the datagrid after subscription or unsubscription
I load the data of the grid like that
#PostConstruct
public void init() {
packages = packagehelper.getAllPackages();
getCurrentUserSubscritions();
}
and here is the xhtml file
<h:form id="form">
<p:growl id="growl" showDetail="true" sticky="false" life="8000" />
<p:dataGrid var="package" value="#{packageView.packages}" columns="3"
>
<p:column>
<f:facet name="header">
Cars for Sale
</f:facet>
<p:panel header="#{package.id}" style="text-align:center">
<h:panelGrid columns="2" style="width:100%">
<p:graphicImage width="100px" name="images/#{package.imageurl}"/>
<h:outputText value="#{package.name}" />
<h:outputText value="#{package.value} EGP for #{package.duration} Days " />
<h:outputText value="#{package.description}" />
<p:commandButton ajax="true" update=":pack" value="Subscribe" rendered="#{!packageView.IsPackageActive(package.id)}" action="#{packageView.Subscribe()}" >
<f:setPropertyActionListener value="#{package.id}" target="#{packageView.packageID}" />
<f:setPropertyActionListener value="#{package.duration}" target="#{packageView.packageDuration}" />
</p:commandButton>
<p:commandButton action="#{packageView.Unsubscribe}" update=":pack" ajax="true" value="Cancel" rendered="#{packageView.UserHasPackage(package.id) and packageView.IsPackageActive(package.id) }">
<f:setPropertyActionListener value="#{package.id}" target="#{packageView.packageID}" />
<f:setPropertyActionListener value="#{package.duration}" target="#{packageView.packageDuration}" />
</p:commandButton>
</h:panelGrid>
</p:panel>
</p:column>
</p:dataGrid>
</h:form>
When an suscribe or unsuscribe action is completed, you should actualize the DataGrid trough its ID, it is, set an ID to the DataGrid and put such id in the update property of the buttons.
For example:
<p:dataGrid id="datalist" .../>
<p:commandButton action="#{packageView.Unsubscribe}" update="datalist" .../>
And when the action of the button is submited set the packages in null, so when the update action of the DataGrid update the packages they should be called again of the persistence or data base.
It is important to consider how to reference the elements in update property. You can see this answer

Primefaces datatable update datatable

I have a problem with primefaces datatables. I have one datatable with some entries and a column with a button inside. If the button is pressed a popup is opened with another datatable. The entries in the second datatable are depending on the row in which the button is pressed.
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Entries" widgetVar="edit_entries" modal="true"
resizable="false">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</p:dialog>
</form>
Bean2
public void updateEntries(Item selectedItem) {
this.entriesList = this.entriesQuery.getAllEntriesByItemID(selectedItem.getId());//db query could take some time
System.out.println("entrieslist size: " + this.entriesList.size()); //prints the correct size
}
The problem is that there are no entries listed in the popup datatable although there are some in the list after the db query.
Any ideas how to fix this bug?
Thanks in advance!
UPDATE 1:
<!-- first datatable -->
<h:form id="list">
<p:dataTable id="list1" var="item" value="#{bean1.itemlist}"
rowKey="#{item.id}" selection="#{bean1.selectedItem}"
selectionMode="single">
<p:column headerText="ID">
<h:outputText value="#{item.id}" />
</p:column>
...
<p:column headerText="Edit Entries">
<p:commandButton value="Edit Entries" update=":dialogUpdateEntries"
actionListener="#{bean2.updateEntries(item)}" ajax="true"
oncomplete="PF('edit_entries').show()" />
</p:column>
</p:dataTable>
</h:form>
<!-- Second datatable in the popup -->
<p:dialog header="Edit Enries" id="dialogUpdateEntries" widgetVar="edit_entries" modal="true"
resizable="false">
<h:form id="formEntriesList">
<p:dataTable id="list2" var="entry"
value="#{bean2.entriesList}" rowKey="#{entry.id}"
selection="#{bean2.selectedEntry}" selectionMode="single">
<p:column headerText="Entry Number">
<h:outputText value="#{entry.number}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton value="Save" oncomplete="PF('edit_entries').hide()" />
</f:facet>
</form>
</p:dialog>
You're indeed not updating the data table in the dialog. JSF doesn't automatically update the view on change of the model, you have to explicitly tell the view to do so. You can use the ajax action component's update attribute for this. This takes a JSF client ID which can be found by rules as outlined in this related answer: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar".
Given the markup as shown in the question, that'll be
<p:commandButton ... update=":list:list2" />
However, there's another potential problem. You're using <p:dialog modal="true"> inside a form instead of giving the dialog its own form. This way the dialog may not be available in the HTML DOM tree as JavaScript (the one responsible for dealing with ajax stuff) would expect to find it. Giving the dialog its own form should fix this matter. It'll also fix the potential future problems with invoking actions from inside the dialog as handled in this related question: <p:commandbutton> action doesn't work inside <p:dialog>.
<h:form id="viewForm">
...
<p:commandButton ... update=":editDialog" />
...
</h:form>
<p:dialog id="editDialog" modal="true">
<h:form id="editForm">
...
</h:form>
</p:dialog>
Try adding update="list2" to Edit Entries command button (even update="#widgetVar(edit_entries)" should work).
If, because of page layout and structure, you can't target the second datatable using above suggestions, then add styleClass="tList2" to second table, and update it with update="#(.tList2)" on edit button.

Primefaces's p:rowExpansion not working inside p:outputPanel?

I'm currently working with primeface's p:rowExpansion and noticed that it's not working inside a p:outputPanel. Here's a sample code:
<p:commandButton action="#{xxxSearchBean.search()}" value="Search" update="messages resultPanel" styleClass="button"></p:commandButton>
<p:outputPanel id="resultPanel">
<p:panel rendered="#{xxxSearchBean.hasResults()}">
<ui:include src="xxxSearchView.xhtml">
<ui:param name="searchBean" value="#{xxxSearchBean}" />
</ui:include>
</p:panel>
</p:outputPanel>
The included view:
<p:accordionPanel activeIndex="0">
<p:tab title="Criminal Results">
<p:dataTable var="c" value="#{searchBean.results}">
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column headerText="Last Name">
<h:outputText value="#{c.lastname}" />
</p:column>
<p:column headerText="First Name">
<h:outputText value="#{c.firstname}" />
</p:column>
<p:rowExpansion>
<p:panelGrid columns="4"
columnClasses="form-field-label,value,form-field-label,value">
<h:outputText value="Label" />
<h:outputText value="Value" />
</p:panelGrid>
</p:rowExpansion>
</p:dataTable>
</p:tab>
</p:accordionPanel>
The above code successfully show the result grid when there are results, but when I click the rowExpansion it doesn't work.
When I moved out the panel and remove the rendered property, the row expansion worked. But I don't want to show the grid on page load :-(
Any idea?
I don't know if <p:rowExpansion> really doesn't work with <p:outputPanel>. But since you don't need any special features of <p:outputPanel>, you can just use <h:panelGroup> instead. :)
I was able to solved the problem by changing the backing bean annotation from #Model to #Conversation scope, then start the conversation the moment the view is render.

update primefaces or jsf view after ajax call on submit button

I am trying to update a primefaces form (wizard-first step) after an ajax command button request with no success. The command button that makes the actual ajax call is on a dialog. I would like after submitting the request to force my view to refresh.
The command button deletes a record from a datatable. It works fine, record is deleted but when dialog is hidden the datatable keeps displaying the deleted record. I would like to force it somehow to refresh. Any ideas? Could I do it from my backing bean reviewManagerBean.deleteProtocol() method?
Here is the code (my BackBean is viewScoped):
<h:form id="reviewManagerForm">
...
<pe:masterDetail id="masterDetail" level="#{reviewManagerBean.currentLevel}" showBreadcrumb="false" selectLevelListener="#{reviewManagerBean.levelListener}" >
<f:facet name="header" >
<h:panelGroup layout="block" style="margin-top: 10px;" >
<h:panelGroup styleClass="levelTitle ui-state-default ui-corner-all wizard-breadcrumbs#{reviewManagerBean.currentLevel eq 1 ? 'ui-state-hover' : ''}">
<h:outputText value="1: Protocol picker"/>
</h:panelGroup>
...
<p:messages id="mainMessagesPanel" showDetail="true" closable="true" />
</h:panelGroup>
</f:facet>
<pe:masterDetailLevel level="1">
<p:panel id="panel1" header="List of available protocols">
<p:dataTable id="protocolsDataTable" var="cRProtocol" rowKey="#{cRProtocol.revProtId}" value="#{reviewManagerBean.cRReviewProtocolList}"
widgetVar="protocolsTable"
...
selection="#{reviewManagerBean.selectedReviewProtocol}"
selectionMode="single" >
...
<p:ajax event="rowSelect" listener="#{reviewManagerBean.setSelectedRow}" />
<p:ajax event="rowUnselect" listener="#{reviewManagerBean.unsetSelectedRow}"/>
...
<p:column sortBy="#{cRProtocol.revProtTitle}" headerText="Title" style="width:200px;text-align:center;">
<h:outputText value="#{cRProtocol.revProtTitle}" />
</p:column>
...
<p:column>
<p:commandButton value="Delete" onclick="dlg5.show()"
update=":reviewManagerForm:deleteSingleProtocol"
disabled="#{reviewManagerBean.checkifProtocolIsOpen(cRProtocol)}"
ajax="true" process=":reviewManagerForm:deleteSingleProtocol" />
</p:column>
</p:dataTable>
</p:panel>
...
<p:dialog id="dialog-deleteprotocol" header="Delete Image Type" widgetVar="dlg5" dynamic="true" modal="true" resizable="false">
<p:panelGrid id="deleteSingleProtocol">
<p:row>
<p:column>
<h:outputText value="Id:" style="font-weight:bold; padding-right:10px" />
</p:column>
<p:column>
<h:outputText value="#{reviewManagerBean.selectedReviewProtocol.revProtId}" />
</p:column>
</p:row>
...
<p:column>
<p:commandButton id='protocolDelete'
value='Delete'
action='#{reviewManagerBean.deleteProtocol()}'
ajax="true"
onclick="dlg5.hide()" icon="ui-icon-disk"
update=":reviewManagerForm:protocolsDataTable"
process=":reviewManagerForm:deleteSingleProtocol" />
</p:column>
</p:row>
</p:panelGrid>
</p:dialog>
Your datatable should be re-rendered properly, you would have gotten an exception otherwise (something like component with id :reviewManagerForm:protocolsDataTable could not be found).
This means that #{reviewManagerBean.cRReviewProtocolList} will get called again. You need to remove the item from that list. This is appropriately done from #{reviewManagerBean.deleteProtocol}.
When #{reviewManagerBean.cRReviewProtocolList} is called after the removal, your datatable will get updated.

How to set selected item in bean in <p:dataList>

I am using p:dataList because I am developing a PrimeFaces mobile view displaying a list of items. When clicking on any item, another pm:view of the same view should be displayed. But the bean should be notified of the selected item.
Unfortunately I couldn't find a way to update the bean successfully: <p:ajax> inside dataTable throws this exception:
<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent
Using <f:setPropertyActionListener> inside the iterative element fails too because I get:
<f:setPropertyActionListener> Parent is not of type ActionSource
This is my code:
<pm:view id="instrumentsView" >
<pm:content >
<h:form id="instrumentsList" >
<p:dataList var="instrument" value="#{instrumentBean.subscribedInstruments}" >
<h:outputLink value="#newView" >#{instrument.longName}</h:outputLink>
<f:setPropertyActionListener value="#{instrument}" target="#{instrumentBean.selectedInstrument}" />
</p:dataList>
</h:form>
</pm:content>
</pm:view>
Clearly, I am using dataList and outputLink because as far as I understand, they are the components optimized for the use in PrimeFaces mobile lists. But I am available to find other options if necessary.
I found out in the showcase (example titled News) the correct way of handling the problem:
<p:dataList var="instrument" value="#{instrumentBean.subscribedInstruments}" >
<p:column >
<p:commandLink value="#{instrument.longName}" action="pm:newView" update=":compId">
<f:setPropertyActionListener value="#{instrument}" target="#{instrumentBean.selectedInstrument}" />
</p:commandLink>
</p:column>
</p:dataList>
There is a topic explaining this in the primefaces documentation.
Selecting Data (page 124)
indexed_primefaces_users_guide_3_5.pdf
http://www.primefaces.org/documentation.html
Here is the content
<h:form id="carForm">
<p:dataGrid var="car" value="#{carBean.cars}" columns="3" rows="12">
<p:panel header="#{car.model}">
<p:commandLink update=":carForm:display" oncomplete="dlg.show()">
<f:setPropertyActionListener value="#{car}"
target="#{carBean.selectedCar}"
<h:outputText value="#{car.model}" />
</p:commandLink>
</p:panel>
</p:dataGrid>
<p:dialog modal="true" widgetVar="dlg">
<h:panelGrid id="display" columns="2">
<f:facet name="header">
<p:graphicImage value="/images/cars/#{car.manufacturer}.jpg" />
</f:facet>
<h:outputText value="Model:" />
<h:outputText value="#{carBean.selectedCar.year}" />
</h:panelGrid>
</p:dialog>
</h:form>

Resources