3/03/2011

Using multiple ice:inputFile components on a page.

Problem


In ICEFaces 1.8 there is no possibility to have multiple ice:inputFile components on one page without hard wiring their actionListeners.


If you want to use an ice:dataTable or ice:panelSeries together with ice:inputFile - forget about it. It won´t work. If you then think about using f:param or f:attribute together with it - forget about it,too. It won´t work either.


The inputFile component of ICEFaces is rendered as an iFrame into the page. This means, that all actionListeners you want to wire to those inputFile components have to exist BEFORE rendering the page. A dataTable is a dynamic component that may change by user interactions on your page. But how would you notify the page that is included in the iFrame about all those changes ? Same goes for parameters : you can´t pass them into the iFrame.


So what do you do ?
In the case of ICEfaces 1.8: Change your UI. Don´t let anyone tell you to use multiple ice:inputFile components. Better use a popup (ice:panelPopup) to force the user to only upload one file at a time.


Solution


In the case of ICEFaces 2.0, you´re saved:


ICEfaces 2.0 supports multiple uploads on the same page. They have replaced the ice:inputFile component by the new ace:fileEntry. You can now use a dataTable to iterate over a list of fileEntries, each with its own actionListener and upload all of them at once, with a single button click.




Here is a snippet that will help you to do it:



<div id="content"><ice:form id="form">
<h:outputText value="Upload your File" />
<ice:dataTable value="#{uploader.list}" var="upl">
<h:column>
<f:facet name="header">
<ice:outputText value="Name" />
</f:facet>
<ice:outputText value="#{upl.name}" />
</h:column>
<h:column>
<f:facet name="header">
<ice:outputText value="Click" />
</f:facet>
<ace:fileEntry label="#{upl.name}"
fileEntryListener="#{upl.listener}" />
</h:column>


</ice:dataTable>
<h:commandButton value="Upload File" type="submit"/>
</ice:form></div>


As you can see, we just use a dataTable that connects to a list of Uploader Beans. We only have one submit button (that needs to be a JSF button) that will call ALL actionListeners when being pushed.
This allows you to have as many uploads on a page as you want.



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.