Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
158
rated 0 times [  160] [ 2]  / answers: 1 / hits: 18941  / 6 Years ago, thu, march 29, 2018, 12:00:00

I am trying to create custom <input type=file> upload button with the name of the uploaded file visible on the button itself after the upload, in React. I am creating this as the component. I found it very difficult to create a codepen demo so I am just uploading the code here (sorry for that).



import React, { Component, PropTypes } from 'react';
import './InputFile.css';

export default class InputFile extends Component {

constructor(props: any)
{
super(props);
this.getUploadedFileName = this.getUploadedFileName.bind(this);
}

getUploadedFileName(selectorFiles: FileList, props) {

const { id } = this.props;

;( function ( document, window, index )
{
var inputs = document.querySelectorAll(`#${id}`);
Array.prototype.forEach.call( inputs, function( input )
{
var label = input.nextElementSibling,
labelVal = label.innerHTML;

input.addEventListener( 'change', function( e )
{
var fileName = '';
if( this.files && this.files.length > 1 )
fileName = ( this.getAttribute( 'data-multiple-caption' ) ||
'' ).replace( '{count}', this.files.length );
else
fileName = e.target.value.split( '\' ).pop();

if( fileName )
label.querySelector( 'span' ).innerHTML = fileName;
else
label.innerHTML = labelVal;
});

// Firefox bug fix
input.addEventListener( 'focus', function(){ input.classList.add(
'has-focus' ); });
input.addEventListener( 'blur', function(){ input.classList.remove(
'has-focus' ); });
});
}( document, window, 0 ));
}


render () {

const { id, text, multiple } = this.props;

return(
<div>
<input id={id} type=file className=km-btn-file data-multiple-caption={count} files selected multiple={multiple} onChange={ (e, id) => this.getUploadedFileName(e.target.files, id)}></input>
<label htmlFor={id} className=km-button km-button--primary km-btn-file-label>
<span>{text}</span>
</label>
</div>
);
}
}

InputFile.propTypes = {
id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
multiple: PropTypes.string,
};


I am importing this component in my other file <InputFile id={'input-file'} text={'Upload File'} multiple={'multiple'}/>



Here is the CSS code



.km-button--primary {
background-color: #5C5AA7;
color: #FFFFFF;
}
.km-button {
border-radius: 3px;
-webkit-appearance: none;
border: none;
outline: none;
background: transparent;
height: 36px;
padding: 0px 16px;
margin: 0;
font-size: 14px;
font-weight: 400;
text-align: center;
min-width: 70px;
transition: all 0.3s ease-out;
}
.km-btn-file {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.km-btn-file-label {
line-height: 36px;
cursor: pointer;
}


The problem I am facing is when I click on the button first time and choose a file to upload it selects the file but does not update the text Upload File with the name of the file. But after the click it the second time it works fine. I don't know why that is happening and for that I need help.



Thanks.


More From » html

 Answers
4

You can use the component 'state' to update your elements.



constructor(props: any)
{
super(props);
this.state = {message:'some initial message'};
}


and for the onChange event do:



getUploadedFileName = (e) => {
let files = e.target.files,
value = e.target.value,
message;
if( files && files.length > 1 ) message = `${files.length} files selected`;
else message = value.split( '\' ).pop();

if(message) this.setState({...this.state,message});
}


and then in the element just bind the value to the state:



<div>
<input id={id} type=file className=km-btn-file
data-multiple-caption={this.state.message}
multiple={multiple}
onChange={this.getUploadedFileName}>
</input>
<label htmlFor={id} className=km-button km-button--primary km-btn-file-label>
<span>{text}</span>
</label>
</div>

[#54821] Monday, March 26, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
dominiquezachariahh

Total Points: 343
Total Questions: 81
Total Answers: 106

Location: Monaco
Member since Fri, Sep 24, 2021
3 Years ago
;