Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit ebe60d7

Browse files
committed
Adding ability to remotely trigger a submit in a form.
1 parent ed621e2 commit ebe60d7

File tree

5 files changed

+66
-24
lines changed

5 files changed

+66
-24
lines changed

docs/api/actions.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ An "untouched" field indicates that this model has not been interacted with yet.
379379
- This action is useful for conditionally displaying error messages based on whether the field has been touched.
380380

381381
<h2 id="actions-submit"></h2>
382-
## `actions.submit(model, promise)`
382+
## `actions.submit(model, [promise])`
383383

384384
Waits for a submission `promise` to be completed, then, if successful:
385385
- Sets `.submitted` property of form for `model` to `true`
@@ -389,9 +389,12 @@ If the promise fails, the action will:
389389
- set `.submitFailed` property of form for `model` to `true`
390390
- set `.errors` property of form for `model` to the response
391391

392+
If a promise is not provided, e.g.: `actions.submit('user')`, then dispatching the action will trigger a `<Form>` with the specified `model` to submit itself.
393+
392394
### Arguments
393395
- `model` _(String | Function)_: the model to be submitted
394396
- `promise` _(Promise)_: the promise that the submit action will wait to be resolved or rejected
397+
- default: `undefined` - will trigger a submit in the `<Form>` component with the specified `model`.
395398
- `options` _(Object)_: submit options:
396399

397400
### Options

src/actions/field-actions.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ const defaultStrategies = {
2121
};
2222

2323
function createFieldActions(s = defaultStrategies) {
24+
const addIntent = (model, intent) => ({
25+
type: actionTypes.ADD_INTENT,
26+
model,
27+
intent,
28+
});
29+
30+
const clearIntents = (model, intents, options = {}) => ({
31+
type: actionTypes.CLEAR_INTENTS,
32+
model,
33+
intents,
34+
options,
35+
});
36+
2437
const focus = (model, value, options = {}) => ({
2538
type: actionTypes.FOCUS,
2639
model,
@@ -155,6 +168,10 @@ function createFieldActions(s = defaultStrategies) {
155168
});
156169

157170
const submit = (model, promise, options = {}) => (dispatch, getState) => {
171+
if (typeof promise === 'undefined') {
172+
return dispatch(addIntent(model, { type: 'submit' }));
173+
}
174+
158175
if (options.validate) {
159176
const form = s.getForm(getState(), model);
160177

@@ -262,19 +279,6 @@ function createFieldActions(s = defaultStrategies) {
262279
errors: true,
263280
});
264281

265-
const addIntent = (model, intent) => ({
266-
type: actionTypes.ADD_INTENT,
267-
model,
268-
intent,
269-
});
270-
271-
const clearIntents = (model, intents, options = {}) => ({
272-
type: actionTypes.CLEAR_INTENTS,
273-
model,
274-
intents,
275-
options,
276-
});
277-
278282
return mapValues({
279283
blur,
280284
focus,

src/components/form-component.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,16 +311,6 @@ function createFormClass(s = defaultStrategy) {
311311

312312
mapValues(finalErrorValidators, validateField);
313313

314-
// const fieldsValidity = mapValues(finalErrorValidators, (validator, field) => {
315-
// const fieldValue = field
316-
// ? s.get(modelValue, field)
317-
// : modelValue;
318-
319-
// const fieldValidity = getValidity(validator, fieldValue);
320-
321-
// return fieldValidity;
322-
// });
323-
324314
dispatch(s.actions.batch(model, [
325315
s.actions.setFieldsErrors(
326316
model,

test/field-actions-spec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,23 @@ Object.keys(testContexts).forEach((testKey) => {
14881488

14891489
store.dispatch(action);
14901490
});
1491+
1492+
it('should add an intent to submit if no promise if given', (done) => {
1493+
const store = createTestStore(testCreateStore({
1494+
testForm: formReducer('test'),
1495+
}), done);
1496+
1497+
store.when(actionTypes.ADD_INTENT, (_, action) => {
1498+
assert.containSubset(action, {
1499+
model: 'test',
1500+
intent: { type: 'submit' },
1501+
});
1502+
});
1503+
1504+
const action = actions.submit('test');
1505+
1506+
store.dispatch(action);
1507+
});
14911508
});
14921509

14931510
describe('validate() (thunk)', () => {

test/form-component-spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,5 +1809,33 @@ Object.keys(testContexts).forEach((testKey) => {
18091809
assert.isFalse(store.getState().testForm.$form.submitFailed);
18101810
});
18111811
});
1812+
1813+
describe('triggering a submit remotely', () => {
1814+
const initialState = getInitialState({ foo: '' });
1815+
1816+
const store = testCreateStore({
1817+
test: modelReducer('test', initialState),
1818+
testForm: formReducer('test', initialState),
1819+
});
1820+
1821+
const handleSubmit = sinon.spy((val) => val);
1822+
1823+
TestUtils.renderIntoDocument(
1824+
<Provider store={store}>
1825+
<Form
1826+
model="test"
1827+
onSubmit={handleSubmit}
1828+
>
1829+
<Control model=".foo" />
1830+
</Form>
1831+
</Provider>
1832+
);
1833+
1834+
it('should call onSubmit() prop when submit intent is remotely triggered', () => {
1835+
store.dispatch(actions.submit('test'));
1836+
1837+
assert.isTrue(handleSubmit.calledOnce);
1838+
});
1839+
});
18121840
});
18131841
});

0 commit comments

Comments
 (0)