Skip to content

Commit

Permalink
fix: introduced field computed prop
Browse files Browse the repository at this point in the history
Introduced field `computed` prop
  • Loading branch information
foxhound87 committed Apr 25, 2023
1 parent 8492ee9 commit c2d9244
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 6.3.1 (master)
- Introduced field `computed` prop. To handle nested array fields computed values.

# 6.3.0 (master)
- Introduced Forms Composer
- Introduced Functional Computed Field Props
Expand Down
1 change: 1 addition & 0 deletions src/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ export default class Base implements BaseInterface {

const props = {
$value: _.get(initial[SeparatedPropsMode.values], path),
$computed: _try(SeparatedPropsMode.computed),
$label: _try(SeparatedPropsMode.labels),
$placeholder: _try(SeparatedPropsMode.placeholders),
$default: _try(SeparatedPropsMode.defaults),
Expand Down
44 changes: 23 additions & 21 deletions src/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,28 +298,30 @@ export default class Field extends Base implements FieldInterface {
newVal = newVal.trim();
}
if (this.$value === newVal) return;
// handle numbers
if (this.state.options.get(OptionsEnum.autoParseNumbers, this)) {
if (_.isNumber(this.$initial)) {
if (
new RegExp("^-?\\d+(,\\d+)*(\\.\\d+([eE]\\d+)?)?$", "g").exec(newVal)
) {
this.$value = this.$converter(_.toNumber(newVal));
this.$changed ++;
if (!this.actionRunning) {
this.state.form.$changed ++;
};
return;
}
}
}
if (this.handleSetNumberValue(newVal)) return;
this.$value = this.$converter(newVal);
this.$changed ++;
if (!this.actionRunning) {
this.state.form.$changed ++;
};
}

handleSetNumberValue(newVal: any): boolean {
if (!this.state.options.get(OptionsEnum.autoParseNumbers, this))
return false;

if (_.isNumber(this.$initial) || this.type == 'number') {
if (new RegExp("^-?\\d+(,\\d+)*(\\.\\d+([eE]\\d+)?)?$", "g").exec(newVal)) {
this.$value = this.$converter(_.toNumber(newVal));
this.$changed ++;
if (!this.actionRunning) {
this.state.form.$changed ++;
};
return true;
}
}
}

get actionRunning() {
return this.submitting || this.clearing || this.resetting;
}
Expand Down Expand Up @@ -580,10 +582,10 @@ export default class Field extends Base implements FieldInterface {
.find((s) => s.substring(structPath.length) === "[]")
: !!Array.isArray(_.get(struct, this.path));

const { $type, $input, $output, $converter } = $props;
const { $type, $input, $output, $converter, $computed } = $props;

if (_.isPlainObject($data)) {
const { type, input, output, converter } = $data;
const { type, input, output, converter, computed } = $data;

this.name = _.toString($data.name || $key);
this.$type = $type || type || "text";
Expand All @@ -595,8 +597,8 @@ export default class Field extends Base implements FieldInterface {
fallbackValueOption,
isEmptyArray,
type: this.type,
unified: $data.value,
separated: $props.$value,
unified: computed || $data.value,
separated: $computed || $props.$value,
fallback: $props.$initial,
});

Expand Down Expand Up @@ -634,8 +636,8 @@ export default class Field extends Base implements FieldInterface {
fallbackValueOption,
isEmptyArray,
type: this.type,
unified: $data,
separated: $props.$value,
unified: $computed || $data,
separated: $computed || $props.$value,
});

this._value = retrieveFieldPropFunc(value)
Expand Down
2 changes: 2 additions & 0 deletions src/models/FieldProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum FieldPropsEnum {
fields = "fields",
ref= "ref",
type = "type",
computed = "computed",
value = "value",
initial = "initial",
default = "default",
Expand Down Expand Up @@ -80,6 +81,7 @@ export enum FieldPropsOccurrence {
}

export enum SeparatedPropsMode {
computed = 'computed',
values = 'values',
labels = 'labels',
placeholders = 'placeholders',
Expand Down
1 change: 1 addition & 0 deletions src/models/FormInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default interface FormInterface extends BaseInterface {
export interface FieldsDefinitions {
struct?: string[];
fields?: any;
computed?: any;
values?: any;
labels?: any;
placeholders?: any;
Expand Down
4 changes: 3 additions & 1 deletion src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface PropsGroupsInterface {
validation: string[];
separated: string[];
occurrences: {
[index: string]: "some" | "every";
[index: string]: FieldPropsOccurrence;
};
}

Expand Down Expand Up @@ -64,6 +64,7 @@ export const props: PropsGroupsInterface = {
FieldPropsEnum.disabled,
],
separated: [
SeparatedPropsMode.computed,
SeparatedPropsMode.values,
SeparatedPropsMode.labels,
SeparatedPropsMode.placeholders,
Expand Down Expand Up @@ -91,6 +92,7 @@ export const props: PropsGroupsInterface = {
SeparatedPropsMode.refs,
],
functions: [
FieldPropsEnum.computed,
FieldPropsEnum.observers,
FieldPropsEnum.interceptors,
FieldPropsEnum.converter,
Expand Down
2 changes: 2 additions & 0 deletions tests/data/_.nested.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import $V2 from "./forms/nested/form.v2";
import $V3 from "./forms/nested/form.v3";
import $V4 from "./forms/nested/form.v4";
import $Z from "./forms/nested/form.z";
import $X from "./forms/nested/form.x";

export default {
$A,
Expand Down Expand Up @@ -61,4 +62,5 @@ export default {
$V3,
$V4,
$Z,
$X,
};
2 changes: 1 addition & 1 deletion tests/data/forms/flat/form.q.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Form } from '../../../../src';
const fields = [{
name: 'username',
label: 'Username',
value: 'SteveJobs',
computed: () => 'SteveJobs', // test computed value
}, {
name: 'email',
label: 'Email',
Expand Down
66 changes: 66 additions & 0 deletions tests/data/forms/nested/form.x.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { expect } from "chai";
import { Form } from "../../../../src";

export default new Form(
{
fields: [
"products[].name",
"products[].qty",
"products[].amount",
"products[].total",
"total"
],
computed: {
'products[].total': ({ field }) => {
const qty = field.container()?.$('qty')?.value;
const amount = field.container()?.$('amount')?.value;
return qty * amount;
},

'total': ({ form }) =>
form.$("products")?.reduce((acc, field) => acc + field.$("total").value, 0),

},
labels: {
"products[].name": "Product Name",
"products[].qty": "Quantity",
"products[].amount": "Amount $"
},
placeholders: {
"products[].name": "Insert Product Name"
},
types: {
"products[].qty": "number",
"products[].amount": "number",
"products[].total": "number"
},
},
{
name: '$x',
options: {
strictSelect: false,
autoParseNumbers: true,
},
hooks: {
onInit(form) {
form.$("products").add();
form.$("products").add();
form.$("products[0].qty").set(2);
form.$("products[0].amount").set(5);
form.$("products[1].qty").set(3);
form.$("products[1].amount").set(5);

describe("Check computed values", () => {
it("form $x products[0].total value", () =>
expect(form.$('products[0].total').value).to.be.equal(10));

it("form $x products[1].total value", () =>
expect(form.$('products[1].total').value).to.be.equal(15));

it("form $x total value", () =>
expect(form.$('total').value).to.be.equal(25));
});
}
}
}
);

0 comments on commit c2d9244

Please sign in to comment.