Currently the .file-custom class uses a pseudo-element for setting the "Choose file..." string. Instead of hardcoding that string in the styles, we could instead defer to the markup by using the attr() function.
<label class="file">
<input type="file" id="file">
<span class="file-custom"></span>
</label>
could become:
<label class="file">
<input type="file" id="file">
<span class="file-custom" data-content-value="Choose file..."></span>
</label>
with css like this:
.file-custom:after {
content: attr(data-content-value);
}
As noted in the existing v4 documentation, there is no way to dynamically update that string without using javascript. However, even with javascript it's not easy to update the content value of the pseudo element. By moving the value to the markup, it's much easier to make changes using javascript.
The attr function seems to be well supported. If there is a different attribute other than data-content-value, that'd be fine too.
I'd be happy to make a pull request, just let me know.
I'm following the above method and it is working like charm. With pSeudo element we can't do much. Please do change design.
+1
@psoots solution is working like a charm.
I just add data-content-value to the span :
<label class="file col-sm-offset-2 col-sm-10">
<input type="file" id="form_profilePicture" name="form[profilePicture]">
<span class="file-custom" data-content-value="Choose file..."></span>
</label>
Then I change the .file-custom::after into _custom-forms.scss like this :
.file-custom::after {
content: attr(data-content-value);
}
And then, I just add these jQuery lines to make it work with all the input[type="file"] on the page :
$('input[type="file"]').on('change', function() {
$(this).next('.file-custom').attr('data-content-value', $(this)[0].files[0].name);
});
Thanks @psoots for this little solution that is working like a charm :+1:
For Bootstrap 4 Alpha 3, the markup has been changed:
For the HTML, it is now:
<label class="custom-file">
<input type="file" name="upload" class="custom-file-input" />
<span class="custom-file-control" data-content-value="Choose file..."></span>
</label>
For the CSS:
.custom-file-control:lang(en)::after {
content: attr(data-content-value);
}
For JS:
$('input[type="file"]').on('change', function() {
$(this).next('.custom-file-control').attr('data-content-value', $(this)[0].files[0].name);
});
For me I had to change slightly the JS to make the above solution work:
$(document).on('change', 'input[type="file"]', function() {
$(this).next('.custom-file-control').attr('data-content-value', $(this)[0].files[0].name);
});
Here's one solution in React + JSX (using the CSS above from @pinglamb ).
Tested with Bootstrap 4 Alpha 4.
<label className="custom-file">
<input
type="file"
className="custom-file-input"
ref={(input) => this.fileInput = input}
onChange={() => {
// files.length is 0 if no file was chosen.
const files = this.fileInput.files
this.setState({
chosenFileName: files.length ? files[0].name : null
})
}}
/>
<span
className="custom-file-control"
data-content-value={ this.state.chosenFileName || "Choose file..." }
/>
</label>
Closing as duplicate of #20813 given that issue has more activity around it.
Most helpful comment
@psoots solution is working like a charm.
I just add
data-content-valueto thespan:Then I change the
.file-custom::afterinto_custom-forms.scsslike this :And then, I just add these jQuery lines to make it work with all the
input[type="file"]on the page :Thanks @psoots for this little solution that is working like a charm :+1: