101

I am struggling with bootstrap 4 file browser. If I use custom-file-control I will see Choose file value all the time. https://v4-alpha.getbootstrap.com/components/forms/#file-browser

I would like to change the value of choose file after the file has been chosen. This value is actually hidden in css .custom-file-control:lang(en)::after and I do not know how to access and change it in javascript. I can get the value of chosen file like this:

document.getElementById("exampleInputFile").value.split("\\").pop();

not I need to change

.custom-file-control:lang(en)::after {
    content: "Choose file...";
}

somehow

link: http://codepen.io/Matoo125/pen/LWobNp

Matej Vrzala M4
  • 1,364
  • 2
  • 13
  • 20
  • This question has been answered before here: http://stackoverflow.com/questions/37713126/bootstrap-show-file-name-after-select – Nathaniel Flick Apr 06 '17 at 09:01
  • not really, I asked how to change css property content, because that is where Bootstrap 4 has the text is renders in this approach. I do not see the value – Matej Vrzala M4 Apr 06 '17 at 09:17
  • but I want to access it dynamically based on the input value. How can I do that with css? – Matej Vrzala M4 Apr 06 '17 at 12:06
  • First, have you managed to change the placeholder/button value with CSS? The process of selecting the value has been answered in the other question – Carol Skelly Apr 06 '17 at 12:26
  • I can select the value with JS, but in bootstrap 4 this 'placeholder' value is in ::after { content : "..." } and I need to change that to see changes – Matej Vrzala M4 Apr 06 '17 at 12:30
  • Same question for [Bootstrap 5](https://stackoverflow.com/q/65770908/) – Gleb Kemarsky Dec 31 '21 at 14:26
  • If using Bootstrap 5, try [this way](https://stackoverflow.com/a/73138618/8706905) , some tricks are used but just works fine. – SteveHu Aug 09 '22 at 03:35

18 Answers18

133

Updated 2021

Bootstrap 5

Custom file input no longer exists so to change Choose file... you'd need to use JS or some CSS like this.

Bootstrap 4.4

Displaying the selected filename can also be done with plain JavaScript. Here's an example that assumes the standard custom-file-input with label that is the next sibling element to the input...

document.querySelector('.custom-file-input').addEventListener('change',function(e){
  var fileName = document.getElementById("myInput").files[0].name;
  var nextSibling = e.target.nextElementSibling
  nextSibling.innerText = fileName
})

https://codeply.com/p/LtpNZllird

Bootstrap 4.1+

Now in Bootstrap 4.1 the "Choose file..." placeholder text is set in the custom-file-label:

<div class="custom-file" id="customFile" lang="es">
        <input type="file" class="custom-file-input" id="exampleInputFile" aria-describedby="fileHelp">
        <label class="custom-file-label" for="exampleInputFile">
           Select file...
        </label>
</div>

Changing the "Browse" button text requires a little extra CSS or SASS. Also notice how language translation works using the lang="" attribute.

.custom-file-input ~ .custom-file-label::after {
    content: "Button Text";
}

https://codeply.com/go/gnVCj66Efp (CSS)
https://codeply.com/go/2Mo9OrokBQ (SASS)

Another Bootstrap 4.1 Option

Alternatively you can use this custom file input plugin

https://www.codeply.com/go/uGJOpHUd8L/file-input


Bootstrap 4 Alpha 6 (Original Answer)

I think there are 2 separate issues here..

<label class="custom-file" id="customFile">
        <input type="file" class="custom-file-input">
        <span class="custom-file-control form-control-file"></span>
</label>

1 - How the change the initial placeholder and button text

In Bootstrap 4, the initial placeholder value is set on the custom-file-control with a CSS pseudo ::after element based on the HTML language. The initial file button (which isn't really a button but looks like one) is set with a CSS pseudo ::before element. These values can be overridden with CSS..

#customFile .custom-file-control:lang(en)::after {
  content: "Select file...";
}

#customFile .custom-file-control:lang(en)::before {
  content: "Click me";
}

2 - How to get the selected filename value, and update the input to show the value.

Once a file is selected, the value can be obtained using JavaScript/jQuery.

$('.custom-file-input').on('change',function(){
    var fileName = $(this).val();
})

However, since the placeholder text for the input is a pseudo element, there's no easy way to manipulate this with Js/jQuery. You can however, have a another CSS class that hides the pseudo content once the file is selected...

.custom-file-control.selected:lang(en)::after {
  content: "" !important;
}

Use jQuery to toggle the .selected class on the .custom-file-control once the file is selected. This will hide the initial placeholder value. Then put the filename value in the .form-control-file span...

$('.custom-file-input').on('change',function(){
  var fileName = $(this).val();
  $(this).next('.form-control-file').addClass("selected").html(fileName);
})

You can then handle the file upload or re-selection as needed.

Demo on Codeply (alpha 6)

Carol Skelly
  • 351,302
  • 90
  • 710
  • 624
81

I just solved it this way

Html:

<div class="custom-file">
   <input id="logo" type="file" class="custom-file-input">
   <label for="logo" class="custom-file-label text-truncate">Choose file...</label>
</div>

JS:

$('.custom-file-input').on('change', function() { 
   let fileName = $(this).val().split('\\').pop(); 
   $(this).next('.custom-file-label').addClass("selected").html(fileName); 
});

Note: Thanks to ajax333221 for mentioning the .text-truncate class that will hide the overflow within label if the selected file name is too long.

Elnoor
  • 3,401
  • 4
  • 24
  • 39
  • 2
    Thanks for the `.split('\\').pop()` part! – spaceemotion Feb 25 '18 at 19:13
  • @spaceemotion happy it helped – Elnoor Feb 26 '18 at 08:08
  • 1
    FWIW, I had to add `type="file"` to the `` tag. But otherwise, worked great. – ghukill Mar 09 '18 at 16:38
  • 1
    @ghukill my answer was a quick design thingy, but i will just add the `type` attribute too, for those who will copy. Thanks – Elnoor Mar 09 '18 at 22:24
  • 5
    Worth saying you can hide the overflow with **text-truncate** like this `class='custom-file-label text-truncate'` – ajax333221 Jul 08 '18 at 03:22
  • @ajax333221 that is awesome, didn't know about that class. Thanks. I just adjust ed answer. – Elnoor Jul 09 '18 at 16:08
  • @ajax333221 Using `text-truncate` I don't get ellipsis... If I don't use it, the text overruns the box (expected). But if I use `text-truncate` it just inserts text all the up to the end and stops (mid-letter depending on length). I even tried adding an inline style with `text-overflow: ellipsis;`, but no luck. Is this expected? – user8897013 Apr 01 '19 at 07:46
18

As of Bootstrap 4.3 you can change placeholder and button text inside the label tag:

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />

<div class="custom-file">
  <input type="file" class="custom-file-input" id="exampleInputFile">
  <label class="custom-file-label" for="exampleInputFile" data-browse="{Your button text}">{Your placeholder text}</label>
</div>
Andrei Veshtard
  • 528
  • 9
  • 12
9

For changing the language of the file browser:
As an alternate to what ZimSystem mentioned (override the CSS), a more elegant solution is suggested by the bootstrap docs: build your custom bootstrap styles by adding languages in SCSS
Read about it here: https://getbootstrap.com/docs/4.0/components/forms/#file-browser

Note: you need to have the lang attribute properly set in your document for this to work

For updating the value on file selection:
You could do it with inline js like this:

   <label class="custom-file">
      <input type="file" id="myfile" class="custom-file-input" onchange="$(this).next().after().text($(this).val().split('\\').slice(-1)[0])">
      <span class="custom-file-control"></span>
   </label>

Note: the .split('\\').slice(-1)[0] part removes the C:\fakepath\ prefix

Razvan Pocaznoi
  • 409
  • 3
  • 4
  • 3
    Nice. Using this to add to all custom file inputs: `$('.custom-file-input').change(function () { $(this).next().after().text($(this).val().split('\\').slice(-1)[0]); });` – Jason Jan 29 '18 at 04:22
6

Bootstrap 4

More details are here https://learncodeweb.com/snippets/browse-button-in-bootstrap-4-with-select-image-preview/

Today I need to create a browse button with a multi-upload files option all the above snippets are not good for me.

The official Bootstrap example is also not working when I select multiple files.

I come up with this code maybe will help others in the future.

$(document).ready(function() {
  $('input[type="file"]').on("change", function() {
    let filenames = [];
    let files = document.getElementById("customFile").files;
    if (files.length > 1) {
      filenames.push("Total Files (" + files.length + ")");
    } else {
      for (let i in files) {
        if (files.hasOwnProperty(i)) {
          filenames.push(files[i].name);
        }
      }
    }
    $(this)
      .next(".custom-file-label")
      .html(filenames.join(","));
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container mt-5">
  <h1 class="text-center">Bootstrap 4 Upload multiple files</h1>
  <div class="col-sm-6 mr-auto ml-auto border p-4">
    <form method="post" enctype="multipart/form-data" action="upload.php">
      <div class="form-group">
        <label><strong>Upload Files</strong></label>
        <div class="custom-file">
          <input type="file" name="files[]" multiple class="custom-file-input form-control" id="customFile">
          <label class="custom-file-label" for="customFile">Choose file</label>
        </div>
      </div>
      <div class="form-group">
        <button type="submit" name="upload" value="upload" id="upload" class="btn btn-block btn-dark"><i class="fa fa-fw fa-upload"></i> Upload</button>
      </div>
    </form>
  </div>
</div>

The working code example is given here with bootstrap 3 and bootstrap 4.3.1.

https://codepen.io/mianzaid/pen/GeEbYV

Zaid Bin Khalid
  • 748
  • 8
  • 25
  • 1
    Actually, the most useful answer for me so +1. Minor improvement: add 'form-control' class to label element. – Saša Dec 06 '19 at 10:05
3

For Bootstrap v.5

document.querySelectorAll('.form-file-input')
        .forEach(el => el.addEventListener('change', e => e.target.parentElement.querySelector('.form-file-text').innerText = e.target.files[0].name));

Affect all file input element. No need to specify elements id.

Persk
  • 639
  • 2
  • 6
  • 15
2

In case, if you need a no jquery solution

<label class="custom-file">
      <input type="file" id="myfile" class="custom-file-input" onchange="this.nextElementSibling.innerText = this.files[0].name">
      <span class="custom-file-control"></span>
</label>
DP101
  • 183
  • 4
  • 11
2

Here is the answer with blue box-shadow,border,outline removed with file name fix in custom-file input of bootstrap appear on choose filename and if you not choose any file then show No file chosen.

    $(document).on('change', 'input[type="file"]', function (event) { 
        var filename = $(this).val();
        if (filename == undefined || filename == ""){
        $(this).next('.custom-file-label').html('No file chosen');
        }
        else 
        { $(this).next('.custom-file-label').html(event.target.files[0].name); }
    });
    input[type=file]:focus,.custom-file-input:focus~.custom-file-label {
        outline:none!important;
        border-color: transparent;
        box-shadow: none!important;
    }
    .custom-file,
    .custom-file-label,
    .custom-file-input {
        cursor: pointer;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
    <div class="container py-5">
    <div class="input-group mb-3">
      <div class="input-group-prepend">
        <span class="input-group-text">Upload</span>
      </div>
      <div class="custom-file">
        <input type="file" class="custom-file-input" id="inputGroupFile01">
        <label class="custom-file-label" for="inputGroupFile01">Choose file</label>
      </div>
    </div>
    </div>
Soham Patel
  • 125
  • 5
1

I just add this in my CSS file and it works:

.custom-file-label::after{content: 'New Text Button' !important;}


Robson Sousa
  • 465
  • 4
  • 9
1

With the help of jquery, it can be done like this. Code:

$("input.custom-file-input").on("change",function(){if(this.files.length){var filename=this.file[0].name;if(filename.length>23){filename=filename.substr(0,11)+"..."+filename.substr(-10);}$(this).siblings(".custom-file-label").text(filename);}});
Rajan Sharma
  • 2,211
  • 3
  • 21
  • 33
1

You can try below given snippet to display the selected file name from the file input type.

document.querySelectorAll('input[type=file]').forEach( input => {
    input.addEventListener('change', e => {
        e.target.nextElementSibling.innerText = input.files[0].name;
    });
});
Kiran Maniya
  • 8,453
  • 9
  • 58
  • 81
codex fast
  • 11
  • 1
1

For "bootstrap_4_layout.html.twig":

document.querySelector('.custom-file-input').addEventListener('change',function(e){
   this.nextElementSibling.innerText = this.files[0].name;
});
Arkadiusz G.
  • 1,024
  • 10
  • 24
0

Solution based on @Elnoor answer, but working with multiple file upload form input and without the "fakepath hack":

HTML:

<div class="custom-file">
    <input id="logo" type="file" class="custom-file-input" multiple>
    <label for="logo" class="custom-file-label text-truncate">Choose file...</label>
</div>

JS:

$('input[type="file"]').on('change', function () {
    let filenames = [];
    let files = document.getElementById('health_claim_file_form_files').files;

    for (let i in files) {
        if (files.hasOwnProperty(i)) {
            filenames.push(files[i].name);
        }
    }

    $(this).next('.custom-file-label').addClass("selected").html(filenames.join(',    '));
});
Sicaa
  • 153
  • 1
  • 8
0

Bootstrap 4.4:

Show a choose file bar. After a file is chosen show the file name along with its extension

<div class="custom-file">
    <input type="file" class="custom-file-input" id="idEditUploadVideo"
     onchange="$('#idFileName').html(this.files[0].name)">
    <label class="custom-file-label" id="idFileName" for="idEditUploadVideo">Choose file</label>
</div>
Aseem
  • 5,848
  • 7
  • 45
  • 69
0

In case you want to use it globally on all custom inputs use following jQuery code:

$(document).ready(function () {
    $('.custom-file-input').on('change', function (e) {
         e.target.nextElementSibling.innerHTML = e.target.files[0].name;
    });
});
Simon Tribus
  • 396
  • 2
  • 11
0

Bootstrap 5.2 Custom file input without CSS.

Image enter image description here

Html Code

<div class="input-group">   
     <input type="file" id="uploadFile_Plan_PDF" class="Zupload" accept="application/pdf" hidden/>
     <button type="button" class="btn btn-outline-secondary">
      <i class="fa-solid fa-file-pdf"></i>
     </button>
     <input readonly="readonly" type="text" class="form-control">                                
     <button type="button" class="btn btn-outline-secondary" disabled>
      <i class="fa-solid fa-eye"></i>
     </button>
     <button type="button" class="btn btn-outline-secondary">
      <i class="fa-solid fa-times"></i>
     </button>
</div>

Js Code

const collection_uploadFile = document.querySelectorAll(".Zupload");
for (let i = 0; i < collection_uploadFile.length; i++) {
  let uploadFile = collection_uploadFile[i]
  let buttonUpload = uploadFile.nextElementSibling;
  let textBoxUpload = buttonUpload.nextElementSibling;
  let buttonView = textBoxUpload.nextElementSibling;
  let buttonClear = buttonView.nextElementSibling;              

  uploadFile.addEventListener('change', function (e) {
    textBoxUpload.value = this.value;
    buttonView.disabled = this.value?false:true;
  });
  buttonUpload.addEventListener('click', function (e) {uploadFile.click();});
  textBoxUpload.addEventListener('click', function (e) {uploadFile.click();});
  buttonClear.addEventListener('click', function (e) {
    uploadFile.value =""; 
    uploadFile.dispatchEvent(new Event("change"));
  });
}

Demo

Zupload on jsfiddle

m-zemmouri
  • 123
  • 8
-1
 <!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>
  <div class="custom-file">
    <input type="file" class="custom-file-input" id="inputGroupFile01">
    <label class="custom-file-label" for="inputGroupFile01">Choose file</label>
  </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
 <script>
$(function() {
  $(document).on('change', ':file', function() {var input = $(this), numFiles = input.get(0).files ? input.get(0).files.length : 1,
        label = input.val().replace(/\\/g, '/').replace(/.*\//, '');input.trigger('fileselect', [numFiles, label]);
  });
  $(document).ready( function() {
      $(':file').on('fileselect', function(event, numFiles, label) {var input = $(this).parents('.custom-file').find('.custom-file-label'),
      log = numFiles > 1 ? numFiles + ' files selected' : label;if( input.length ) {input.text(log);} else {if( log ) alert(log);}});
  });
});
 </script>
  </body>
</html>
-1

Without JQuery

HTML:

<INPUT type="file" class="custom-file-input"  onchange="return onChangeFileInput(this);">

JS:

function onChangeFileInput(elem){
  var sibling = elem.nextSibling.nextSibling;
  sibling.innerHTML=elem.value;
  return true;
}

KliG

KliG
  • 1