Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.

Commit

Permalink
fix: fixed disabling form
Browse files Browse the repository at this point in the history
  • Loading branch information
artemnih committed Mar 5, 2019
1 parent 891979d commit c83132b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 39 deletions.
2 changes: 1 addition & 1 deletion dist/ngx-forms.js

Large diffs are not rendered by default.

98 changes: 74 additions & 24 deletions src/app/layouts/groups/group.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,51 +119,44 @@ describe('GroupComponent Core', () => {
});

describe('Conditional Disabling', () => {

it('should enable the fields', () => {
component.model = { title: 'test' };
component.formConfig = { form: [{ fields: [{ type: 'text', name: 'title' }], enableWhen: { rules: [{ field: "title", equals: ["test"] }] } }] } as FormConfig;
component.ngOnInit();
component.ngAfterViewInit();
expect(component.fconfig[0].fields[0].disabled).toBeFalsy();
});

it('should disable the fields', () => {
component.model = { title: 'test' };
component.formConfig = { form: [{ fields: [{ type: 'text', name: 'title' }], enableWhen: { rules: [{ field: "title", equals: ["test1"] }] } }] } as FormConfig;
component.ngOnInit();
expect(component.fconfig[0].fields[0].disabled).toBeTruthy();
});
});

describe('checkRules()', () => {

it('should not run rules', () => {
const model = { title: 'test' };
const cfg = {};
expect(component.checkRules(cfg, model, [])).toBeUndefined();
const cfg = { enableWhen: { rules: [] } };
expect(component.checkRules(cfg.enableWhen, model, [])).toBeTruthy();
});

it('should not run rules where there are none', () => {
const model = { title: 'test' };
const cfg = { enableWhen: { rules: [] } };
const cfg = { rules: [] };
expect(component.checkRules(cfg, model, [])).toBeTruthy();
});

it('should run one rule and return true', () => {
const model = { title: 'test' };
const cfg = { enableWhen: { rules: [{ field: "title", equals: ["test"] }] } };
const cfg = { rules: [{ field: "title", equals: ["test"] }] };
expect(component.checkRules(cfg, model, [])).toBeTruthy();
});

it('should run one rule, wrap equals, and return true', () => {
const model = { title: 'test' };
const cfg = { enableWhen: { rules: [{ field: "title", equals: "test" }] } };
const cfg = { rules: [{ field: "title", equals: "test" }] };
expect(component.checkRules(cfg, model, [])).toBeTruthy();
});

it('should run one rule and return false', () => {
const model = { title: 'test' };
const cfg = { enableWhen: { rules: [{ field: "title", equals: ["test1"] }] } };
const cfg = { rules: [{ field: "title", equals: ["test1"] }] };
expect(component.checkRules(cfg, model, [])).toBeFalsy();
});

Expand All @@ -174,7 +167,7 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeTruthy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeTruthy();
});

it('should check default field value and return false when rule match', () => {
Expand All @@ -184,7 +177,7 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeFalsy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeFalsy();
});

it('should check default field value and return true whrn all rules match', () => {
Expand All @@ -195,7 +188,7 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.And, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeTruthy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeTruthy();
});

it('should check default field false when value is not found', () => {
Expand All @@ -206,25 +199,25 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.And, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeFalsy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeFalsy();
});

it('should run multiple rules with `and` and return false when one does not match', () => {
const model = { title: 'test', count: 1 };
const cfg = { enableWhen: { type: ConditionType.And, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1123] }] } };
expect(component.checkRules(cfg, model, [])).toBeFalsy();
expect(component.checkRules(cfg.enableWhen, model, [])).toBeFalsy();
});

it('should run multiple rules with `or` and return false when none match', () => {
const model = { title: 'test', count: 1 };
const cfg = { enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test1"] }, { field: "count", equals: [1123] }] } };
expect(component.checkRules(cfg, model, [])).toBeFalsy();
expect(component.checkRules(cfg.enableWhen, model, [])).toBeFalsy();
});

it('should run multiple rules with `or` and return true when one match', () => {
const model = { title: 'test', count: 1 };
const cfg = { enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1222] }] } };
expect(component.checkRules(cfg, model, [])).toBeTruthy();
expect(component.checkRules(cfg.enableWhen, model, [])).toBeTruthy();
});

it('should check default field value and return true when one OR rules match', () => {
Expand All @@ -235,7 +228,7 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeTruthy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeTruthy();
});

it('should check default field false when value is not found', () => {
Expand All @@ -246,7 +239,65 @@ describe('GroupComponent Core', () => {
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
};
expect(component.checkRules(cfg, {}, cfg.fields)).toBeFalsy();
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeFalsy();
});

it('should skip all rule checks', () => {
const cfg = {
fields: [
{ name: "title", type: 'text' },
{ name: "count", type: 'text' }
],
enableWhen: { type: "XOR", rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
};
expect(component.checkRules(cfg.enableWhen, {}, cfg.fields)).toBeFalsy();
});

it('should run rules in ngAfterViewInit', () => {
component.lookups = { test: [{ t: 'a' }, { t: 'b' }, { t: 'c' }] };;
component.formConfig = {
form: [{
fields: [
{ name: "title", type: 'text' },
{ name: "count", type: 'text' }
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
}]
} as FormConfig;
component.ngOnInit();
component.ngAfterViewInit();
expect(component.group.controls.title.enabled).toBeFalsy();
});

it('should run rules in ngAfterViewInit and return true', () => {
component.lookups = { test: [{ t: 'a' }, { t: 'b' }, { t: 'c' }] };;
component.formConfig = {
form: [{
fields: [
{ name: "title", type: 'text', value: 'test' },
{ name: "count", type: 'text', value: 1 }
],
enableWhen: { type: ConditionType.Or, rules: [{ field: "title", equals: ["test"] }, { field: "count", equals: [1] }] }
}]
} as FormConfig;
component.ngOnInit();
component.ngAfterViewInit();
expect(component.group.controls.title.enabled).toBeTruthy();
});

it('should not run rules in ngAfterViewInit', () => {
component.lookups = { test: [{ t: 'a' }, { t: 'b' }, { t: 'c' }] };;
component.formConfig = {
form: [{
fields: [
{ name: "title", type: 'text' },
{ name: "count", type: 'text' }
]
}]
} as FormConfig;
component.ngOnInit();
component.ngAfterViewInit();
expect(component.group.controls.title.enabled).toBeTruthy();
});

});
Expand All @@ -266,7 +317,6 @@ describe('GroupComponent Core', () => {
});
});


describe('subscription()', () => {
it('should extract lookup', () => {
component.lookups = { test: [{ t: 'a' }, { t: 'b' }, { t: 'c' }] };;
Expand Down
25 changes: 11 additions & 14 deletions src/app/layouts/groups/group.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { FieldConfig, ILookup, PanelGroup, ConditionType } from '../../../types'; // todo: move specific types here
import { FieldConfig, ILookup, ConditionType, Law } from '../../../types'; // todo: move specific types here
import { BaseLayout } from '../base-layout';
import { Subscription } from 'rxjs';
import { AbstractControl } from '@angular/forms';
Expand All @@ -17,6 +17,8 @@ export class GroupComponent extends BaseLayout implements OnInit, AfterViewInit,
public selected = 0;
public fconfig = [];

private allFields = [];

public ngOnInit(): void {

this.fconfig = JSON.parse(JSON.stringify(this.formConfig.form));
Expand Down Expand Up @@ -47,17 +49,14 @@ export class GroupComponent extends BaseLayout implements OnInit, AfterViewInit,
// }

});

this.allFields = this.allFields.concat(fields);
});

}

public checkRules(groupCfg: PanelGroup, model, allFields: FieldConfig[]): boolean {
let enabled = true;
if (!groupCfg.enableWhen) { return; }

const enableWhen = groupCfg.enableWhen;

if (!enableWhen.rules.length) { return true; }
public checkRules(enableWhen: Law, model, allFields: FieldConfig[]): boolean {
if (!enableWhen || !enableWhen.rules || !enableWhen.rules.length) { return true; }

const checkRule = rule => {
let field;
Expand All @@ -67,16 +66,14 @@ export class GroupComponent extends BaseLayout implements OnInit, AfterViewInit,
};

if (enableWhen.type === ConditionType.Or || !enableWhen.type) {
enabled = enableWhen.rules.some(checkRule);
return enableWhen.rules.some(checkRule);
}

if (enableWhen.type === ConditionType.And) {
enabled = enableWhen.rules.every(checkRule);
return enableWhen.rules.every(checkRule);
}

// leave if() conditions in case other logic operators needed (XOR, etc)

return enabled;
return false;
}

validateGroup(index) {
Expand All @@ -87,7 +84,7 @@ export class GroupComponent extends BaseLayout implements OnInit, AfterViewInit,
this.fconfig.forEach((group, index) => {

if (group.enableWhen) {
if (!this.checkRules(group, this.model, this.groupProps[index].fields)) {
if (!this.checkRules(group.enableWhen, this.model, this.allFields)) {
this.groupProps[index].fields
.forEach((f: FieldConfig) => {
const control = this.group.get(f.name);
Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ export interface FormsExtensions {
fieldDictionary?: FieldDictionary;
layoutDictionary?: LayoutDictionary;
}

export interface Law {
type?: ConditionType;
rules: ConditionRule[];
}

0 comments on commit c83132b

Please sign in to comment.