Skip to content

Commit 7f9ed39

Browse files
committed
feat(manager): implement fileInput features
1 parent 861ed8e commit 7f9ed39

File tree

5 files changed

+129
-3
lines changed

5 files changed

+129
-3
lines changed

packages/form-state-manager/src/files/use-field.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ const sanitizeValue = (event: OnChangeEvent): any => {
1818
return event;
1919
}
2020

21+
if (event.target.type === 'file') {
22+
return {
23+
inputValue: event.target.value,
24+
inputFiles: event.target.files
25+
};
26+
}
27+
2128
return event?.target.type === 'checkbox' ? event.target.checked : event?.target.value;
2229
}
2330

@@ -123,7 +130,15 @@ const useField = ({
123130
() => {
124131
formOptions().afterSilentRegistration({ name, internalId: id });
125132

133+
if (type === 'file') {
134+
formOptions().registerInputFile(name);
135+
}
136+
126137
return () => {
138+
if (type === 'file') {
139+
formOptions().unregisterInputFile(name);
140+
}
141+
127142
unregisterField({ name, clearOnUnmount, internalId: id, value: finalClearedValue });
128143
};
129144
},
@@ -171,6 +186,10 @@ const useField = ({
171186
valueToReturn = [];
172187
}
173188

189+
if (type === 'file' && typeof valueToReturn === 'object') {
190+
valueToReturn = valueToReturn.inputValue;
191+
}
192+
174193
return {
175194
input: {
176195
value: valueToReturn,

packages/form-state-manager/src/tests/files/use-field.test.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,4 +1366,72 @@ describe('useField', () => {
13661366
expect(wrapper.find('select').props().value).toEqual(['hamsters']);
13671367
});
13681368
});
1369+
1370+
describe('fileInput', () => {
1371+
let Dummy;
1372+
let wrapper;
1373+
1374+
beforeEach(() => {
1375+
managerApi = createManagerApi({});
1376+
1377+
Dummy = (props) => {
1378+
const {
1379+
input: { value, ...rest }
1380+
} = useField(props);
1381+
return (
1382+
<React.Fragment>
1383+
<input {...rest} />
1384+
<span>{value}</span>
1385+
</React.Fragment>
1386+
);
1387+
};
1388+
});
1389+
1390+
it('register inputFile name and uregister', async () => {
1391+
expect(managerApi().fileInputs).toEqual([]);
1392+
wrapper = mount(
1393+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1394+
<Dummy name="field" type="file" />
1395+
</FormManagerContext.Provider>
1396+
);
1397+
expect(managerApi().fileInputs).toEqual(['field']);
1398+
1399+
await act(async () => {
1400+
wrapper.unmount();
1401+
});
1402+
wrapper.update();
1403+
1404+
expect(managerApi().fileInputs).toEqual([]);
1405+
});
1406+
1407+
it('sanitize value', async () => {
1408+
wrapper = mount(
1409+
<FormManagerContext.Provider value={{ ...managerApi(), formOptions: managerApi }}>
1410+
<Dummy name="field" type="file" />
1411+
</FormManagerContext.Provider>
1412+
);
1413+
1414+
await act(async () => {
1415+
wrapper
1416+
.find('input')
1417+
.first()
1418+
.simulate('change', {
1419+
target: {
1420+
value: '/path/',
1421+
files: ['blabla'],
1422+
type: 'file'
1423+
}
1424+
});
1425+
});
1426+
wrapper.update();
1427+
1428+
expect(managerApi().getState().values).toEqual({
1429+
field: {
1430+
inputFiles: ['blabla'],
1431+
inputValue: '/path/'
1432+
}
1433+
});
1434+
expect(wrapper.find('span').text()).toEqual('/path/');
1435+
});
1436+
});
13691437
});

packages/form-state-manager/src/tests/utils/manager-api.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,4 +2283,26 @@ describe('managerApi', () => {
22832283
expect(managerApi().getState().pristine).toEqual(true);
22842284
expect(managerApi().getState().dirty).toEqual(false);
22852285
});
2286+
2287+
describe('fileInput', () => {
2288+
const managerApi = createManagerApi({ onSubmit: jest.fn() });
2289+
2290+
expect(managerApi().fileInputs).toEqual([]);
2291+
2292+
managerApi().registerInputFile('name');
2293+
2294+
expect(managerApi().fileInputs).toEqual(['name']);
2295+
2296+
managerApi().registerInputFile('name');
2297+
2298+
expect(managerApi().fileInputs).toEqual(['name', 'name']);
2299+
2300+
managerApi().unregisterInputFile('name');
2301+
2302+
expect(managerApi().fileInputs).toEqual(['name']);
2303+
2304+
managerApi().unregisterInputFile('name');
2305+
2306+
expect(managerApi().fileInputs).toEqual([]);
2307+
});
22862308
});

packages/form-state-manager/src/types/manager-api.d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export type PauseValidation = () => void;
4545
export type ResumeValidation = () => void;
4646
export type SetConfig = (attribute: keyof CreateManagerApiConfig, value: any) => void;
4747
export type AfterSilentRegistration = (field: Omit<FieldConfig, 'render'>) => void;
48-
48+
export type RegisterInputFile = (name: string) => void;
49+
export type UnregisterInputFile = (name: string) => void;
4950
export interface AsyncWatcherRecord {
5051
[key: number]: Promise<unknown>;
5152
}
@@ -116,7 +117,9 @@ export type ManagerApiFunctions =
116117
| 'pauseValidation'
117118
| 'resumeValidation'
118119
| 'setConfig'
119-
| 'afterSilentRegistration';
120+
| 'afterSilentRegistration'
121+
| 'registerInputFile'
122+
| 'unregisterInputFile';
120123

121124
export interface ManagerState {
122125
values: AnyObject;
@@ -173,6 +176,9 @@ export interface ManagerState {
173176
validating: boolean;
174177
visited: AnyBooleanObject;
175178
destroyOnUnregister: boolean | undefined;
179+
fileInputs: Array<any>;
180+
registerInputFile: RegisterInputFile;
181+
unregisterInputFile: UnregisterInputFile;
176182
}
177183

178184
export type ManagerApi = () => ManagerState;

packages/form-state-manager/src/utils/manager-api.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ export const initialFormState = (initialValues: AnyObject = {}): Omit<ManagerSta
182182
touched: {},
183183
valid: true,
184184
validating: false,
185-
visited: {}
185+
visited: {},
186+
fileInputs: []
186187
});
187188

188189
const createManagerApi: CreateManagerApi = ({
@@ -238,6 +239,8 @@ const createManagerApi: CreateManagerApi = ({
238239
setConfig,
239240
afterSilentRegistration,
240241
destroyOnUnregister,
242+
registerInputFile,
243+
unregisterInputFile,
241244
...initialFormState(initialValues)
242245
};
243246
let inBatch = 0;
@@ -992,6 +995,14 @@ const createManagerApi: CreateManagerApi = ({
992995
});
993996
}
994997

998+
function registerInputFile(name: string): void {
999+
state.fileInputs.push(name);
1000+
}
1001+
1002+
function unregisterInputFile(name: string): void {
1003+
state.fileInputs.splice(state.fileInputs.indexOf(name), 1);
1004+
}
1005+
9951006
return managerApi;
9961007
};
9971008

0 commit comments

Comments
 (0)