Upload multiple files in one form using h:inputFile JSF - jsf-2

I have one datatable and each row have a <h:inputFile>, one button to add a new row for table.
Each time button fired, the previous inputFiles were cleared -> that is not my aim.
I want to store all the upload file then submit.
The simple code here:
<h:form id="documentForm" enctype="multipart/form-data">
<p:dataTable value="#{documentList}" var="obj" >
<f:facet name="header">
<p:commandButton value="Add new row" action="#{contractDetailController.addNewDoc}" update="documentTable" ajax="false"/>
</f:facet>
<p:column headerText="Document File">
<h:inputFile value="#{obj.file}" />
</p:column>
</p:dataTable>
</h:form>
Through BalusC comment in this post : How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable, it seems no way to store previous upload file through requests.
Is there any solutions for my case

Related

Calling listener in p:selectBooleanCheckbox without refreshing the whole dataTable in Primefaces

I have a Primeface selectBooleanCheckbox in a column of a DataTable. Inside there is a <p:ajax that on check calls the method in the listener (mybean.checkCell(cell.field2)) and saves the status of the checkbox.
My problem is that the entire p:dataTable is refreshed when I check.
How do I call mybean.checkCell(cell.field2) without refreshing the whole dataTable?
Here is my code:
<p:dataTable var="cell" value="#{mybean.mycells}" widgetVar="cell" emptyMessage="No cells" filteredValue="#{mybean.filteredCells}">
<p:column filterBy="#{cell.field1}" headerText="Field1" filterMatchMode="contains">
<h:outputText value="#{cell.field1}" />
</p:column>
<p:column headerText="Checkbox">
<p:selectBooleanCheckbox value="#{cell.check}" partialSubmit="true">
<p:ajax process="#this" partialSubmit="true" update=":form:messages" listener="#{mybean.checkCell(cell.field2)}" onstart="PF('statusDialog').show();" oncomplete="PF('statusDialog').hide();" />
</p:selectBooleanCheckbox>
</p:column>
</p:dataTable>
You are updating the component specified in update=":form:messages" everytime click the checkbox. I guess "messages" ID belongs to a container where the datatable is in. If it is not right, i don't understend why the databled gets updated. If it is right, just delete the update attribute or update something that does not contain the datatable inside.

Prevent state saving for specific element

I have the following scenario:
I have a dataTable in which I have a column with the following code
<f:facet name="header">
<h:selectBooleanCheckbox styleClass="checkall"
id="my-id-chk" />
<h:outputLabel for="my-id-chk" />
</f:facet>
<h:selectBooleanCheckbox rendered="#{row.selectable}" value="#{row.selected}"
styleClass="checkall_remover" id="row-chk" />
<h:outputLabel for="row-chk" />
When I want to select all rows and delete them:
1) I click on the h:selectBooleanCheckbox in the <f:facet name="header"> and with js I select all rows checkboxes
2) Click on delete button that execute that dataTable and deletes all rows on server , that delete button also renders the dataTable so the deleted rows will be removed from it
Now the thing is that the h:selectBooleanCheckbox in the <f:facet name="header"> keeps its state (checked state)
How can I make that h:selectBooleanCheckbox in the <f:facet name="header"> to be unchecked ?
The solution that I use right now is to render the dataTable from a "proxy" button that is located in other h:form <-- Using that technique causes the h:selectBooleanCheckbox in the <f:facet name="header"> not to remember its state.
But I prefer a cleaner solution without using additional h:form
(I use MyFaces 2.2.3 with Tomcat 7)
Just use plain HTML. JSF state is indeed saved on server side, but HTML state not.
<f:facet name="header">
<input type="checkbox" class="checkall"
id="my-id-chk" />
<label for="my-id-chk" />
</f:facet>
An alternative would be to create a custom component whereby getters/setters don't delegate to UIComponent#getStateHelper() but instead to local properties.

ignoreValidationFailed doesn´t work inside p:dataTable

I am using actionListener ajax call inside datatable and trying to do the following :
skip validation
update the model with the inserted values
I knew that omnifaces utility liberary by BalusC can do this using o:ignoreValidationFailed
But it failed with me to work inside primefaces datatable.
Also I found that it failed to work inside ui:repeat in another post here
I dont know if its a bug or not.
here is my code example
<o:form id ="trans_desc_form">
<p:outputPanel id="stkdetailsid">
<p:dataTable id="transactiondetailsid" value="#{stockTransactionsBean.stkTransHeader.stkTransDetailsList}"
var="stkTransDet" rowIndexVar="rowIndex">
<p:column>
<f:facet name="header">
<h:outputText value="Item Code" />
</f:facet>
<p:autoComplete id="dd" required="true"
value="#{stkTransDet.item}" var="i" itemLabel="#{i.itemno} #{i.itemnamee}"
itemValue="#{i}" converter="itemsConverter"
completeMethod="#{stockTransactionsBean.completeItems}"/>
</p:column>
<p:column>
<p:commandButton value="-" update="#form" process="#form"
actionListener="#{stockTransactionsBean.removeRow(rowIndex)}">
<o:ignoreValidationFailed />
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
</o:form>
As a workaround, I added
1- add a condition to the required field to know if the ajax come from submit button or not
to the autoComplete component where the trans_desc_form is thte entire form id and savetransid is the submit button save id
required="#{!empty param['trans_desc_form:savetransid']}"/>
2- I removed #NotNull from my JPA entity which force the validation
#JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
//#NotNull
private Item item;
To skip validation you can use the immediate="true" attribute on your p:commandButton

I can't update from within a facet

I'm using primefaces 3.3 with JSF 2.1. In the code below, I have a primeFaces dataTable that contains rows of data drawn from the database which is correctly activated from a tree component on the left part of my page. The dataTable displays and behaves correctly. I have a delete functionality that calls "update" which refreshes my dataTable and reflects my changes after the database was updated. My problem is with with f:facet (id="header"). Contained in that facet is a commandLink that creates a new row in my dataTable. It works in the sense that my database is correctly updated. The dataTable is not refreshed after this. In order to refresh my dataTable, I have to click on another node in my tree component (on the left of the page) and then return to the original treeNode to see my dataTable perfectly updated. What can I add to my code to update the dataTable dynamically?
Unfortunately, I can't add all my permutations that I've tried here - I've spent a long time on this problem - and your inputs will be greatly appreciated!
<h:form id="formRight" >
<p:dataTable var="material" value="#{entityCrudTreeBean.materialList}" id="materials" editable="true" paginator="true" rows="10" sortBy="#{material.name}">
<p:ajax event="rowEdit" listener="#{entityCrudTreeBean.onEditRow}"/>
<f:facet id="header" name="header">
In-Cell Material Editing
<br />
<p:commandLink id="create" value="Add new material" action="#{entityCrudTreeBean.createNewMaterial}" update=":formRight"/>
</f:facet>
<p:column headerText="Name" style="width:125px">
<p:cellEditor>
...
</p:cellEditor>
</p:column>
<p:column headerText="Options" style="width:10px" >
<p:rowEditor />
<p:commandLink id="delete" action="#{entityCrudTreeBean.deleteRow(material)}" update=":formRight">
<h:graphicImage value="#{resource['icons:Delete-icon.png']}" />
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
edit:
changing the line to
<p:commandLink id="create" value="Add new material" action="#{entityCrudTreeBean.createNewMaterial}" update=":formRight:materials"/>
doesn't work either
edit:
changing to :
<f:facet id="header" name="header">
In-Cell Material Editing
<br />
<p:commandLink id="create" value="Add new material" ajax="true" process="#this" action="#{entityCrudTreeBean.createNewMaterial}" update="#form"/>
</f:facet>
doesn't solve the problem either.
I had a similar issue as you a while back.
My working code looks like:
<f:facet name="header">Product List
<p:commandLink id="create" value="Add new product" ajax="true" process="#this"
action="#{modelBean.save}" update="#form"/>
</f:facet>
Stephen, you're on the right track!
It was solved in a simpler way: I updated my dataTable list in managed bean - which I did for the delete but not for the insert. Massive oversight there.
This code works:
<p:commandLink id="create" value="Add new material" action="#{entityCrudTreeBean.createNewMaterial}" update=":formRight"/>
Tip for people after me: Primefaces 3.3 has a known issue concerning updating within the dataTable. You need to wrap the dataTable with another component like a layout of a form. Calling update on the wrapper works.
According to the primefaces blog from Aug 15, this has been fixed in 3.4.RC1. But they changed the tree components. I'll wait for the 3.4 final release before upgrading.

Getting the filtered list in datatable

I am trying to filter a datatable using filter field in the column and get the filtered list (which populates datatable) and update another component (Toplam TL Teminati and Toplam Dolar Teminati) according to the filtered list's values in my page.
Is there anyway to do this in Primefaces 2.2.1 and JSF 2? If not can you rec commend a workaround for this case?
Thanks in advance.
To give you an example of how I achieved custom filter logic in my Primefaces 2.2.1 dataTable, I am giving you a scaled version of my code.
<p:dataTable value="#{listBeans.beans}" var="bean" dynamic="true" paginator="true" rows="20" paginatorPosition="bottom"
emptyMessage="No Beans" loadingMessage="Loading. . ." selectionMode="single" selection="#{listBeans.selectedBean}"
id="beanList" widgetVar="beanTable">
<f:facet name="header">
<h:panelGrid columns="4">
<h:outputText value="Bean List" />
<p:outputPanel>
<h:outputText value="Year Filter: " />
<h:selectOneMenu value="#{listBeans.yearFilter}"
onchange="yearFilterBtn.jq.click(); refreshFilters();">
<f:selectItems value="#{listBeans.years}" />
</h:selectOneMenu>
<p:commandButton id="yearFilterBtn" widgetVar="yearFilterBtn" action="#{listBeans.filterYears}"
update="listBeansForm:beanList" style="display:none;" />
</p:outputPanel>
<p:outputPanel>
<h:outputText value="Filter By Beanchild: " />
<p:inputText value="#{listBeans.beanchildFilter}" style="width: 150px; margin-right: 4px;" />
<!-- refreshFilters forces the visitor filter to refresh the selection if column filters are selected. -->
<p:commandButton oncomplete="refreshFilters();" value="Filter"
action="#{listBeans.filterBeanchildren}" update="listBeansForm:beanList" />
</p:outputPanel>
<p:commandButton value="Export to XLS" ajax="false">
<p:dataExporter target="beanList" type="xls" fileName="BeanReport"
excludeColumns="0,5,6" postProcessor="#{listBeans.postProcessExcelReport}" />
</p:commandButton>
</h:panelGrid>
</f:facet>
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column filterStyleClass="filtertag" filterBy="#{bean.beanDateDisplay}" filterMatchMode="startsWith">
....
</p:dataTable>
Without really going into too much detail about the managed bean code, the actions of the command button are essentially passing filter arguments to my BO layer that requery the database for the new list of beans. The explicit update of the dataTable component is needed to refresh the data.
You will notice that on the explicit Beanchild Filter button that is not hidden, I have an oncomplete attribute that references a javascript function called refreshFilters(). I can't remember exactly the problem I had, but I think it is a bug in the 2.2.1 version of Primefaces when a column filter value exists and an asynchronous update occurs within the dataTable itself. Here is the javascript function:
function refreshFilters() {
var filters = jQuery('.filtertag');
var uppedOnce = false;
filters.each(function(idx) {
var curEl = jQuery(this);
if (curEl.val() != '') {
curEl.keyup();
uppedOnce = true;
}
});
if (!uppedOnce) {
jQuery(filters[0]).keyup();
}
}
You can see here that I am locating every DOM element that has the class filtertag, which would be the column filters. I am saying that if a value exists in that field after the server action is complete, then I am manually triggering a keyup event as this will "refilter" the column with the previous value from before.
I am not sure if it is necessary in later versions of Primefaces, I am not even sure it is necessary now, so I suggest trying to do this without the Javascript workaround and if you run into problems cooridnating the two then you can consider using the Javascript.

Resources