Skip to content

Commit f19938e

Browse files
committed
Added docs for file input.
1 parent 1b58598 commit f19938e

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { useState } from 'react';
2+
import FormRenderer from '@data-driven-forms/react-form-renderer/dist/cjs/form-renderer';
3+
import componentTypes from '@data-driven-forms/react-form-renderer/dist/cjs/component-types';
4+
import FormTemplate from '@data-driven-forms/pf4-component-mapper/dist/cjs/form-template';
5+
import TextField from '@data-driven-forms/pf4-component-mapper/dist/cjs/text-field';
6+
import useFieldApi from '@data-driven-forms/react-form-renderer/dist/cjs/use-field-api';
7+
import submitFunction from './upload-handler';
8+
9+
const FileUploadComponent = (props) => {
10+
const { input, label } = useFieldApi(props);
11+
return (
12+
<div>
13+
<label htmlFor={input.name}>{label}</label>
14+
<input id={input.name} {...input} />
15+
</div>
16+
);
17+
};
18+
19+
const componentMapper = {
20+
[componentTypes.TEXT_FIELD]: TextField,
21+
'file-upload': FileUploadComponent
22+
};
23+
24+
const schema = {
25+
fields: [
26+
{
27+
component: componentTypes.TEXT_FIELD,
28+
label: 'Regular test field',
29+
name: 'regular-field'
30+
},
31+
{
32+
component: 'file-upload',
33+
label: 'File upload',
34+
name: 'file-upload-field-name',
35+
type: 'file'
36+
}
37+
]
38+
};
39+
40+
const FormWithFileUpload = () => {
41+
const [values, setValues] = useState();
42+
return (
43+
<div className="pf4">
44+
{values && (
45+
<div>
46+
<h1>See that the files gets destroyed in JSON</h1>
47+
<h2>See console for the stored value</h2>
48+
<pre>{JSON.stringify(values, null, 2)}</pre>
49+
</div>
50+
)}
51+
<FormRenderer
52+
schema={schema}
53+
componentMapper={componentMapper}
54+
FormTemplate={FormTemplate}
55+
onSubmit={async (values, formApi) => {
56+
setValues(values);
57+
console.log('form values', values);
58+
console.log('formApi with fileInputs array', formApi);
59+
const encoded = await submitFunction(values, formApi);
60+
console.log('encoded image', encoded);
61+
}}
62+
/>
63+
</div>
64+
);
65+
};
66+
67+
export default FormWithFileUpload;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import get from 'lodash/get';
2+
3+
// https://stackoverflow.com/questions/36280818/how-to-convert-file-to-base64-in-javascript
4+
const toBase64 = (file) =>
5+
new Promise((resolve, reject) => {
6+
const reader = new FileReader();
7+
reader.readAsDataURL(file);
8+
reader.onload = () => resolve(reader.result);
9+
reader.onerror = (error) => reject(error);
10+
});
11+
12+
const submitFunction = async (values, formApi) => {
13+
const myFile = get(values, formApi.fileInputs[0]); // there can be multiple inputs of this type
14+
const fileFakePath = myFile.inputValue; // the fake path shown as the input value
15+
const fileList = myFile.inputFiles; // list of file renferences that should be uploaded to somewhere
16+
const base64Encoded = await toBase64(fileList[0]); // files list is always an array
17+
const formData = new FormData();
18+
formData.append(formApi.fileInputs[0], fileList[0]);
19+
return {
20+
base64Encoded,
21+
formData
22+
};
23+
};
24+
25+
export default submitFunction;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
import Grid from '@material-ui/core/Grid'
3+
4+
import ListOfContents from '../../src/helpers/list-of-contents';
5+
import CodeExample from '../../src/components/code-example';
6+
7+
<Grid container item>
8+
<Grid item xs={12} md={10}>
9+
10+
# File input
11+
12+
Files cannot be easilly uploaded in JSON payload. In order to upload files usigng the input type *file* you can follow these steps.
13+
14+
## File onChange payload
15+
16+
In order to successfully store the file reference, you have either use an input of type file or use an object with the following shape in your on change function ([visit MDN docs for more info on file upload](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file)).
17+
```jsx
18+
{
19+
target: {
20+
value: string, // usually it is the path to the file
21+
files: FileList // an array of file references
22+
}
23+
}
24+
```
25+
26+
## Getting file from state.
27+
28+
When submitting, you will have to construct the binary via FormData or encode the file to Base64, depending on your use case. Be aware that FormData cannot be sent in the JSON payload. Binaries are destroyed when serializing JSON. There will be a list of field names with the type file avaiable in the submit function arguments.
29+
30+
The `formApi.fileInputs` is an array of field names with `type: file`. Be aware that if your filed name is in nested, you have to use the lodash like method of getting the value from state.
31+
32+
<CodeExample source="components/file-upload/upload-handler" />
33+
34+
<CodeExample source="components/file-upload/file-input" mode="preview" additionalSources="components/file-upload/upload-handler.js" />
35+
36+
</Grid>
37+
<Grid item xs={false} md={2}>
38+
<ListOfContents file="renderer/file-input" />
39+
</Grid>
40+
</Grid>

packages/react-renderer-demo/src/app/src/components/navigation/documentation-pages.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export const docs = [
5151
component: 'data-types',
5252
linkText: 'Data types'
5353
},
54+
{
55+
component: 'file-input',
56+
linkText: 'File input'
57+
},
5458
{
5559
component: 'cleared-value',
5660
linkText: 'Cleared field value'

0 commit comments

Comments
 (0)