Skip to content

Commit

Permalink
feat: introduced computed props and composer
Browse files Browse the repository at this point in the history
introduced computed props and composer
  • Loading branch information
foxhound87 committed Apr 23, 2023
1 parent ed07ffd commit 8492ee9
Show file tree
Hide file tree
Showing 29 changed files with 295 additions and 126 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 6.3.0 (master)
- Introduced Forms Composer
- Introduced Functional Computed Field Props
- Introduced `strictSelect` and `strictSet` form options.
- Form option `strictUpdate` behavior changed (now applied on `update()` action).
- Field prop `validators` does not accept anymore a single function, an array of functions is needed.

# 6.2.3 (master)
- Introduced `applyInputConverterOnInit`, `applyInputConverterOnSet`, `applyInputConverterOnUpdate` form options.
- Introduced `converter` function applied on `set value`.
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@

## Features

- Extensibles Validation Plugins.
- Extensibles [Validation Plugins](https://foxhound87.github.io/mobx-react-form/docs/validation/plugins.html).
- Sync & Async Validation (w/ Promises & automatic errors).
- Nested Fields (w/ Serialization & Validation).
- Nested Forms (w/ Nested Submission & Validation Hooks).
- Event Hooks, Event Handlers & Validation Hooks
- Observers & Interceptors
- Bindings for custom Components.
- [Event Hooks](https://foxhound87.github.io/mobx-react-form/docs/events/event-hooks.html), [Event Handlers](https://foxhound87.github.io/mobx-react-form/docs/events/event-handlers.html) & [Validation Hooks](https://foxhound87.github.io/mobx-react-form/docs/events/validation-hooks.html)
- Functional [Computed Field Props](https://foxhound87.github.io/mobx-react-form/docs/extra/computed-props.html)
- Field Props [Observers & Interceptors](https://foxhound87.github.io/mobx-react-form/docs/extra/mobx-events.html)
- Field [Props Bindings](https://foxhound87.github.io/mobx-react-form/docs/bindings) for custom Components.
- Support for Material UI, React Widgets, React Select & more.
- [Forms Composer](https://foxhound87.github.io/mobx-react-form/docs/extra/composer.html): to handle multi-forms submit, validations and other actions
- Dedicated [DevTools](https://github.com/foxhound87/mobx-react-form-devtools) Package.

<br>
Expand Down Expand Up @@ -105,7 +107,7 @@ const hooks = {
}
```

> See more on the docs about the [Validation Hooks](https://foxhound87.github.io/mobx-react-form/docs/events/validation-hooks.html)
> See more on the docs about the [Validation Hooks](https://foxhound87.github.io/mobx-react-form/docs/events/validation-hooks.html) and the [Event Hooks](https://foxhound87.github.io/mobx-react-form/docs/events/event-hooks.html)
#### Initialize the Form

Expand All @@ -131,7 +133,7 @@ import { observer } from 'mobx-react';

export default observer(({ myForm }) => (
<form onSubmit={myForm.onSubmit}>
<label for={myForm.$('email').id}>
<label htmlFor={myForm.$('email').id}>
{myForm.$('email').label}
</label>
<input {...myForm.$('email').bind()} />
Expand Down
37 changes: 23 additions & 14 deletions src/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default class Base implements BaseInterface {
*/
intercept = (opt: any): any =>
this.MOBXEvent(
_.isFunction(opt)
(typeof opt === 'function')
? { type: "interceptor", call: opt }
: { type: "interceptor", ...opt }
);
Expand All @@ -171,7 +171,7 @@ export default class Base implements BaseInterface {
*/
observe = (opt: any): any =>
this.MOBXEvent(
_.isFunction(opt)
(typeof opt === 'function')
? { type: "observer", call: opt }
: { type: "observer", ...opt }
);
Expand Down Expand Up @@ -200,7 +200,7 @@ export default class Base implements BaseInterface {
onSubmit = (...args: any): any =>
this.execHandler(FieldPropsEnum.onSubmit, args, (e: Event, o = {}) => {
e.preventDefault();
this.submit(o, false);
this.submit(o, { execOnSubmitHook: false });
});

/**
Expand Down Expand Up @@ -329,28 +329,32 @@ export default class Base implements BaseInterface {
/**
Submit
*/
submit(o: any = {}, execHook: boolean = true): Promise<any> {
execHook && this.execHook(FieldPropsEnum.onSubmit, o);
submit(hooks: any = {}, {
execOnSubmitHook = true,
execValidationHooks = true,
validate = true
} = {}): Promise<any> {
execOnSubmitHook && this.execHook(FieldPropsEnum.onSubmit, hooks);
this.$submitting = true;
this.$submitted += 1;

if (!this.state.options.get(OptionsEnum.validateOnSubmit, this)) {
if (!validate || !this.state.options.get(OptionsEnum.validateOnSubmit, this)) {
return Promise
.resolve(this)
.then(action(() => (this.$submitting = false)))
.then(() => this);
}

const exec = (isValid: boolean) => isValid
? this.execHook(ValidationHooks.onSuccess, o)
: this.execHook(ValidationHooks.onError, o);
? this.execHook(ValidationHooks.onSuccess, hooks)
: this.execHook(ValidationHooks.onError, hooks);

return (
this.validate({
showErrors: this.state.options.get(OptionsEnum.showErrorsOnSubmit, this),
})
.then(({ isValid }: any) => {
const handler = exec(isValid);
const handler = execValidationHooks ? exec(isValid) : undefined;
if (isValid) return handler;
const $err = this.state.options.get(OptionsEnum.defaultGenericError, this);
const $throw = this.state.options.get(OptionsEnum.submitThrowsError, this);
Expand Down Expand Up @@ -424,7 +428,9 @@ export default class Base implements BaseInterface {
_.each(fields, (field, key) => {
const $key = _.has(field, FieldPropsEnum.name) ? field.name : key;
const $path = _.trimStart(`${path}.${$key}`, ".");
const $field = this.select($path, null, false);

const strictUpdate = this.state.options.get(OptionsEnum.strictUpdate, this);
const $field = this.select($path, null, strictUpdate);
const $container = this.select(path, null, false) || this.state.form.select(this.path, null, false);
const applyInputConverterOnUpdate = this.state.options.get(OptionsEnum.applyInputConverterOnUpdate, this);

Expand Down Expand Up @@ -604,7 +610,7 @@ export default class Base implements BaseInterface {
recursion: boolean = false
): void {
const err = "You are updating a not existent field:";
const isStrict = this.state.options.get(OptionsEnum.strictUpdate, this);
const isStrict = this.state.options.get(OptionsEnum.strictSet, this);

if (_.isNil(data)) {
this.each((field: any) => field.$value = defaultValue({
Expand Down Expand Up @@ -791,13 +797,14 @@ export default class Base implements BaseInterface {
*/
select(path: string, fields: any = null, isStrict: boolean = true) {
const $path = parsePath(path);

const keys = _.split($path, ".");
const head = _.head(keys);

keys.shift();

let $fields = _.isNil(fields) ? this.fields.get(head) : fields.get(head);
let $fields = _.isNil(fields)
? this.fields.get(head)
: fields.get(head);

let stop = false;
_.each(keys, ($key) => {
Expand All @@ -810,7 +817,9 @@ export default class Base implements BaseInterface {
}
});

if (isStrict) throwError(path, $fields);
if (isStrict && this.state.options.get(OptionsEnum.strictSelect, this)) {
throwError(path, $fields);
}

return $fields;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class Bindings implements BindingsInterface {

register(bindings: FieldPropsType): Bindings {
_.each(bindings, (val, key) => {
if (_.isFunction(val)) _.merge(this.templates, { [key]: val });
if ((typeof val === 'function')) _.merge(this.templates, { [key]: val });
if (_.isPlainObject(val)) _.merge(this.rewriters, { [key]: val });
});

Expand Down
Loading

0 comments on commit 8492ee9

Please sign in to comment.