我正在尝试创建自定义<input type="file">
上传按钮,上传后在按钮上显示上传文件的名称,在React中。我正在创建它作为组件。我发现很难创建一个codepen演示,所以我只是在这里上传代码(对不起)。
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,
};
我正在我的其他文件<InputFile id={'input-file'} text={'Upload File'} multiple={'multiple'}/>
这是CSS代码
.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;
}
我面临的问题是,当我第一次点击按钮并选择要上传的文件时,它会选择文件,但不会更新文本&#34;上传文件&#34;与文件的名称。但是在点击它之后第二次它工作正常。我不知道为什么会这样,为此我需要帮助。
感谢。
答案 0 :(得分:1)
您可以使用组件“state”来更新元素。
constructor(props: any)
{
super(props);
this.state = {message:'some initial message'};
}
并且对于onChange事件执行:
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});
}
然后在元素中将值绑定到状态:
<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>
答案 1 :(得分:0)
您需要将来自props的text属性绑定到您的状态,因此在您的构造函数中,您将不得不这样做;
this.state = {...props};
或
this.state = { text: props.text, id: props.id, multiple: props.multiple };
然后在您想要更新视图值时调用,而不是自己在标签上手动设置 innerHtml ; this.setState({text: new value });
在你的渲染方法中;
const { id, text, multiple } = this.state;
这样做当你调用this.setState时,它告诉React重新渲染你的组件,然后从状态中获取更新的值。