1 | import React, { Component } from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import { CustomInput } from 'reactstrap';
|
4 |
|
5 | const htmlValidationAttrs = ['min', 'max', 'required'];
|
6 |
|
7 | let id = 0;
|
8 | class FilePicker extends Component {
|
9 | constructor(props) {
|
10 | super(props);
|
11 |
|
12 | this.state = {};
|
13 | }
|
14 |
|
15 | id = `filePicker-${(id += 1)}`;
|
16 |
|
17 | onChange = event => {
|
18 | const { files } = event.target;
|
19 | const { onChange } = this.props;
|
20 | this.value = [];
|
21 | for (let i = 0; i < files.length; i++) {
|
22 | this.value[i] = files[i];
|
23 | }
|
24 | this.setState({ value: this.value });
|
25 | this.validate();
|
26 | if (onChange) onChange(event);
|
27 | };
|
28 |
|
29 | reset = () => {
|
30 | this.value = null;
|
31 | this.setState({ value: null });
|
32 | };
|
33 |
|
34 | componentDidMount() {
|
35 | if (this.context.FormCtrl && this.props.name) {
|
36 | this.updateValidations();
|
37 | }
|
38 | }
|
39 |
|
40 | updateValidations(props = this.props) {
|
41 | this.validations = { ...props.validate };
|
42 |
|
43 | Object.keys(props)
|
44 | .filter(val => htmlValidationAttrs.indexOf(val) > -1)
|
45 | .forEach(attr => {
|
46 | if (props[attr]) {
|
47 | this.validations[attr] = this.validations[attr] || {
|
48 | value: props[attr],
|
49 | };
|
50 | } else {
|
51 | delete this.validations[attr];
|
52 | }
|
53 | });
|
54 |
|
55 | this.context.FormCtrl.register(this);
|
56 | this.validate();
|
57 | }
|
58 |
|
59 | validate() {
|
60 | if (this.context.FormCtrl && this.props.name) {
|
61 | this.context.FormCtrl.validate(this.props.name);
|
62 | }
|
63 | }
|
64 |
|
65 | componentWillUnmount() {
|
66 | if (this.context.FormCtrl && this.props.name)
|
67 | this.context.FormCtrl.unregister(this);
|
68 | }
|
69 |
|
70 | getValue() {
|
71 | if (!this.value) return '';
|
72 | return this.props.multiple ? this.value || [] : this.value[0];
|
73 | }
|
74 |
|
75 | render() {
|
76 | const {
|
77 | tag: Tag,
|
78 | maxSize,
|
79 | allowedFileTypes,
|
80 | children,
|
81 | ...props
|
82 | } = this.props;
|
83 | const file = this.state.value && this.getValue();
|
84 | props.id = props.id || props.name || this.id;
|
85 | return children &&
|
86 | props.name &&
|
87 | file &&
|
88 | (!this.props.multiple || file.length > 0) ? (
|
89 | children({ file, clear: this.reset, reset: this.reset })
|
90 | ) : (
|
91 | <Tag
|
92 | value=""
|
93 | type="file"
|
94 | accept={
|
95 | Array.isArray(allowedFileTypes) && allowedFileTypes.length > 0
|
96 | ? allowedFileTypes.join(',')
|
97 | : undefined
|
98 | }
|
99 | size={maxSize ? maxSize.toString() : undefined}
|
100 | {...props}
|
101 | onChange={this.onChange}
|
102 | />
|
103 | );
|
104 | }
|
105 | }
|
106 |
|
107 | FilePicker.propTypes = {
|
108 | tag: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
|
109 | onChange: PropTypes.func,
|
110 | multiple: PropTypes.bool,
|
111 | children: PropTypes.func,
|
112 | name: PropTypes.string,
|
113 | allowedFileTypes: PropTypes.arrayOf(PropTypes.string),
|
114 | maxSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
115 | };
|
116 |
|
117 | FilePicker.defaultProps = {
|
118 | tag: CustomInput,
|
119 | };
|
120 |
|
121 | FilePicker.contextTypes = {
|
122 | FormCtrl: PropTypes.object,
|
123 | };
|
124 |
|
125 | export default FilePicker;
|