Styling file upload button for simple_form_for with Bootstrap in Rails 3
Solution 1
This is how I do it:
- In the view add your form file field and hide it
- Add a styled additional field just to display the file name
-
Add a button to trigger the file browse dialog
<div class="control-group"> <div class="attach-set"> <%= f.input :real_file, input_html: { hidden: true }, label: 'Upload Attachment' %> <div class="input-append"> <input id="file-display" class="input-large uneditable-input" type="text"> <a id="upload-btn" class="btn"><i class="icon-upload-alt"></i> Browse</a> </div> </div> <!-- /attach-set --> </div> <!-- /control-group -->
-
In your JS (Coffee w/ jQuery shown), pass the click from the display button onto the real file input and when they select a file drop the file name in the display text field (I drop the path so that I don't see C:\FakePath....)
$(document).ready -> # ------------------------------------------------------ # pretty-fy the upload field # ------------------------------------------------------ $realInputField = $('#real_file') # drop just the filename in the display field $realInputField.change -> $('#file-display').val $(@).val().replace(/^.*[\\\/]/, '') # trigger the real input field click to bring up the file selection dialog $('#upload-btn').click -> $realInputField.click()
Solution 2
This worked great for me and only requires HTML
<label class="btn btn-primary">
Add a file!
<span style="display:none;">
<%= f.file_field :image, required: true, multiple: true, name: 'picture' %>
</span>
</label>
Solution 3
I ran across and am using Jasny's extension to Bootstrap 3. It seems to work well so far.
Solution 4
No JS required, just plain css
scss
.fileinput-button {
position: relative;
overflow: hidden;
float: left;
margin-right: 4px;
width: 110px;
height: 32px;
input{
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
direction: ltr;
cursor: pointer;
}
}
html / slim
span class="btn btn-success fileinput-button"
i.fa.fa-pencil
span
| Select File
= f.file_field :cover_ar
I recommend using compass for cross browser compatibility
Solution 5
Every Browser has a different type of file input field button and this makes it a pain. You can play a little with css. This has given me a basic styling with JS without the annoying "No file chosen" text in chrome and Safary:
$(document).ready(function() {
$(".your_button").css("width", "80px");
});
Otherwise the best solution is to hide it and show a fake one that intercepts the click:
http://duckranger.com/2012/06/pretty-file-input-field-in-bootstrap/
With respect to the question of how to show that a file has been uploaded, a basic solution with jquery file upload is to detect the upload complete event and replace some of your text with a success message (The exact file name I believe it is not possible to obtain with modern browsers):
$(".your_button").fileupload({
dataType: "json",
done: function(e, data) {
$(".place_for_your_text").text("File uploaded.");
}
});
In summary, a basic solution is to use javascript in your assets to:
- Hide the annoying "No file chosen text" with css.
- Place your "Chose file" text next to the button and give it a class you can reference.
- Replace the text with "File uploaded"
tibbon
Updated on January 15, 2022Comments
-
tibbon over 2 years
Using simple_form_for, Bootstrap and Rails 3. In a form:
<%= f.input :upload, label: 'PDF file:' , input_html: {accept: ('application/pdf') } %>
I don't know how I'd style this so that the "choose file" button can have a different class ('btn btn-primary').
Additionally, when using with Bootstrap at least, its severely misaligned by default. See attached image.
Finally, how do I redefine the text from "No file chosen" to "Chose file" when there isn't one added yet, and show the file name when there is one.
-
Ernesto over 9 yearsGreat answer. I have only one question: what does the 'uneditable-input' class does?
-
BSB over 9 yearsuneditable-input it's a bootstrap class that just disables the input field so that the only way to change the contents is via the file picker
-
Thomas Walther over 9 yearsYou have two small typos in your CSS (one missing semicolon, one missing }), and for Safari support, it is helpful to add
-webkit-transform: translate(-300px, 0)scale(4);
. Other than that, great solution, thanks a lot! -
Wraithseeker over 8 yearsMy file input does not seem to get hidden, does anyone have any idea why?
-
frank almost 8 years@Wraithseeker, The hidden: true is overwritten by display: block of input[type="file"] when I did the inspect input[type="file"] { 1. display: block; } [hidden], template { 2. display: none; } You can add a class inside input_html: {class: 'hidden-input'} and a more specific rule in you scss: products.scss // Product new/edit (ie. _form) input[type="file"].hidden-input { display: none; }
-
Guy almost 8 yearsI had to do this (HAML): = f.input :pic, as: :hidden, input_html: { hidden: true, type: "file", class: "file required" } to hide the original file upload box. Also, to get it readonly the "uneditable-field" class didn't work for me so I added readonly: true. Works great!