Primefaces 5
I have <input type="file" class="ui-fileupload-choose>
in code to upload the files. This input
-Tag is generated automatically from a PrimeFaces component <p:fileUpload>
.
I want to hide the button for input
element and use my own styled button for upload.
So this is the styled button.
<input type="button" onclick="$('#formId\\:uploaderId .ui-fileupload-choose input').click();">
This does function in FF, Chrome and IE9, 10, 11.
But in IE8 nothing happens in upload phase. The "choose file" dialog is shown. The generated input file
has JQuery change event. I believe that this event will not be called, because if I click on input file
button it goes in all browsers.
I've tried
<input type="button" onclick="$('#formId\\:uploaderId .ui-fileupload-choose input').click(); #formId\\:uploaderId ui-fileupload-choose input').trigger('change');">
but it doesn't help.
Also I've tried
$('#formId\\:uploaderId .ui-fileupload-choose input').change(function () {
// Cause the change() event
// to be fired in IE8 et. al.
//some checks against recursion.
alert("I'm in change");
$('#formId\\:uploaderId .ui-fileupload-choose input').change();
});
The function in change is called but it doesn't help either.
What can I do in this situation ?
This is due to a security restriction in IE.
When there's <input type="file"/>
which has either of
display:none
visbilty:hidden
opacity: 0
IE blocks the request to upload the file if it's being called manually (javascript click).
In PrimeFaces case the input file has opacity: 0
.
Here's how the input file looks like without the CSS extra flavours:
The work around is to move that input file outside p:fileUpload
component so it can loose the CSS roles, and append it to a span or div with button styling, that would result an actual click on the file input.
Button
<span class="btn btn-primary btn-file">
<i class="fa fa-upload"></i> Upload File
</span>
javascript
$(document).ready(function() {
$('.ui-fileupload-buttonbar span input[type=file]').addClass('uploadBtn');
$('.btn-file').append($('.uploadBtn'));
});
Something link this:
Now to get it to look nice and work in the same time on all browsers including IE, some CSS should be added.
First ignore the first two CSS classes btn btn-primary
(colors, padding etc..)
The btn-file
is the custom trick:
.btn-file {
position: relative;
overflow: hidden;
}
.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 999px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
cursor: inherit;
display: block;
}
The final result is a button with input file in the background:
The p:fileUpload
component should be hidden:
<p:fileUpload style="display: none" />
In order to display the error messages you can use onchange event for that input file:
$('.uploadBtn').change(function() {
var a = $('.ui-fileupload-content').html(); var b = $('#editUserUploadMessages').html(a);
})
Where #editUserUploadMessages
is a div containing all the messages.
Finally hide the other uploaded files:
#editUserUploadMessages .ui-fileupload-files {
display: none;
}
You can find a small example on github and a Demo
Additional solution to an excellent answer of Hatem.
It is using this SO answer.
You can use html tag <label>
to forward the click to input buton.
<h:form id="formId" >
<style>
#formId\:uploaderId .ui-fileupload-buttonbar {
position: absolute;
left: -10000px;
}
#formId\:uploaderId .ui-fileupload-content {
border: none;
}
</style>
<p:fileUpload id="uploaderId" mode="advanced" auto="true" allowTypes="..." fileLimit="...">
<label for="formId:uploaderId_input">
<span class="fa fa-upload" />
</label>
</h:form>
This way the errors will be shown at point where <p:fileUpload>
is included.