diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.spec.ts
index a54e379cac..883da2295a 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.spec.ts
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.spec.ts
@@ -9,12 +9,9 @@ import {
} from '@angular/forms';
import {
DISABLED_MATCHER_PROVIDER,
- DynamicFormControlRelation,
DynamicFormRelationService,
HIDDEN_MATCHER,
HIDDEN_MATCHER_PROVIDER,
- MATCH_VISIBLE,
- OR_OPERATOR,
REQUIRED_MATCHER_PROVIDER,
} from '@ng-dynamic-forms/core';
@@ -26,6 +23,7 @@ import {
import { FormBuilderService } from '../form-builder.service';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { DsDynamicTypeBindRelationService } from './ds-dynamic-type-bind-relation.service';
+import { getTypeBindRelations } from './type-bind.utils';
describe('DSDynamicTypeBindRelationService test suite', () => {
let service: DsDynamicTypeBindRelationService;
@@ -85,7 +83,7 @@ describe('DSDynamicTypeBindRelationService test suite', () => {
});
it('Should get 1 related form models for mock relation model data', () => {
const testModel = mockInputWithTypeBindModel;
- testModel.typeBindRelations = getTypeBindRelations(['boundType']);
+ testModel.typeBindRelations = getTypeBindRelations(['boundType'], 'dc.type');
const relatedModels = service.getRelatedFormModel(testModel);
expect(relatedModels).toHaveSize(1);
});
@@ -94,7 +92,7 @@ describe('DSDynamicTypeBindRelationService test suite', () => {
describe('Test matchesCondition method', () => {
it('Should receive one subscription to dc.type type binding"', () => {
const testModel = mockInputWithTypeBindModel;
- testModel.typeBindRelations = getTypeBindRelations(['boundType']);
+ testModel.typeBindRelations = getTypeBindRelations(['boundType'], 'dc.type');
const dcTypeControl = new UntypedFormControl();
dcTypeControl.setValue('boundType');
let subscriptions = service.subscribeRelations(testModel, dcTypeControl);
@@ -103,7 +101,7 @@ describe('DSDynamicTypeBindRelationService test suite', () => {
it('Expect hasMatch to be true (ie. this should be hidden)', () => {
const testModel = mockInputWithTypeBindModel;
- testModel.typeBindRelations = getTypeBindRelations(['boundType']);
+ testModel.typeBindRelations = getTypeBindRelations(['boundType'], 'dc.type');
const dcTypeControl = new UntypedFormControl();
dcTypeControl.setValue('boundType');
testModel.typeBindRelations[0].when[0].value = 'anotherType';
@@ -118,7 +116,7 @@ describe('DSDynamicTypeBindRelationService test suite', () => {
it('Expect hasMatch to be false (ie. this should NOT be hidden)', () => {
const testModel = mockInputWithTypeBindModel;
- testModel.typeBindRelations = getTypeBindRelations(['boundType']);
+ testModel.typeBindRelations = getTypeBindRelations(['boundType'], 'dc.type');
const dcTypeControl = new UntypedFormControl();
dcTypeControl.setValue('boundType');
testModel.typeBindRelations[0].when[0].value = 'boundType';
@@ -134,18 +132,3 @@ describe('DSDynamicTypeBindRelationService test suite', () => {
});
});
-
-function getTypeBindRelations(configuredTypeBindValues: string[]): DynamicFormControlRelation[] {
- const bindValues = [];
- configuredTypeBindValues.forEach((value) => {
- bindValues.push({
- id: 'dc.type',
- value: value,
- });
- });
- return [{
- match: MATCH_VISIBLE,
- operator: OR_OPERATOR,
- when: bindValues,
- }];
-}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.ts
index 03ca4b26cf..4f8cff747e 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.ts
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service.ts
@@ -13,7 +13,6 @@ import {
DynamicFormControlModel,
DynamicFormControlRelation,
DynamicFormRelationService,
- MATCH_VISIBLE,
OR_OPERATOR,
} from '@ng-dynamic-forms/core';
import { Subscription } from 'rxjs';
@@ -216,23 +215,4 @@ export class DsDynamicTypeBindRelationService {
return subscriptions;
}
- /**
- * Helper function to construct a typeBindRelations array
- * @param configuredTypeBindValues
- */
- public getTypeBindRelations(configuredTypeBindValues: string[]): DynamicFormControlRelation[] {
- const bindValues = [];
- configuredTypeBindValues.forEach((value) => {
- bindValues.push({
- id: 'dc.type',
- value: value,
- });
- });
- return [{
- match: MATCH_VISIBLE,
- operator: OR_OPERATOR,
- when: bindValues,
- }];
- }
-
}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/type-bind.utils.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/type-bind.utils.ts
new file mode 100644
index 0000000000..1d09e9fafb
--- /dev/null
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/type-bind.utils.ts
@@ -0,0 +1,48 @@
+import {
+ DynamicFormControlRelation,
+ MATCH_ENABLED,
+ MATCH_VISIBLE,
+ OR_OPERATOR,
+} from '@ng-dynamic-forms/core';
+
+/**
+ * Get the type bind values from the REST data for a specific field
+ * The return value is any[] in the method signature but in reality it's
+ * returning the 'relation' that'll be used for a dynamic matcher when filtering
+ * fields in type bind, made up of a 'match' outcome (make this field visible), an 'operator'
+ * (OR) and a 'when' condition (the bindValues array).
+ * @param configuredTypeBindValues array of types from the submission definition (CONFIG_DATA)
+ * @param typeField
+ * @private
+ * @return DynamicFormControlRelation[] array with one relation in it, for type bind matching to show a field
+ */
+export function getTypeBindRelations(configuredTypeBindValues: string[], typeField: string): DynamicFormControlRelation[] {
+ const bindValues = [];
+ configuredTypeBindValues.forEach((value) => {
+ bindValues.push({
+ id: typeField,
+ value: value,
+ });
+ });
+ // match: MATCH_VISIBLE means that if true, the field / component will be visible
+ // operator: OR means that all the values in the 'when' condition will be compared with OR, not AND
+ // when: the list of values to match against, in this case the list of strings from ...
+ // Example: Field [x] will be VISIBLE if item type = book OR item type = book_part
+ //
+ // The opposing match value will be the dc.type for the workspace item
+ //
+ // MATCH_ENABLED is now also returned, so that hidden type-bound fields that are 'required'
+ // do not trigger false validation errors
+ return [
+ {
+ match: MATCH_ENABLED,
+ operator: OR_OPERATOR,
+ when: bindValues,
+ },
+ {
+ match: MATCH_VISIBLE,
+ operator: OR_OPERATOR,
+ when: bindValues,
+ },
+ ];
+}
diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts
index c634c7d876..e4543bcff8 100644
--- a/src/app/shared/form/builder/parsers/field-parser.ts
+++ b/src/app/shared/form/builder/parsers/field-parser.ts
@@ -2,12 +2,7 @@ import {
Inject,
InjectionToken,
} from '@angular/core';
-import {
- DynamicFormControlLayout,
- DynamicFormControlRelation,
- MATCH_VISIBLE,
- OR_OPERATOR,
-} from '@ng-dynamic-forms/core';
+import { DynamicFormControlLayout } from '@ng-dynamic-forms/core';
import { TranslateService } from '@ngx-translate/core';
import uniqueId from 'lodash/uniqueId';
@@ -28,6 +23,7 @@ import {
DynamicRowArrayModel,
DynamicRowArrayModelConfig,
} from '../ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
+import { getTypeBindRelations } from '../ds-dynamic-form-ui/type-bind.utils';
import { FormFieldModel } from '../models/form-field.model';
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { RelationshipOptions } from '../models/relationship-options.model';
@@ -98,7 +94,7 @@ export abstract class FieldParser {
metadataFields: this.getAllFieldIds(),
hasSelectableMetadata: isNotEmpty(this.configData.selectableMetadata),
isDraggable,
- typeBindRelations: isNotEmpty(this.configData.typeBind) ? this.getTypeBindRelations(this.configData.typeBind,
+ typeBindRelations: isNotEmpty(this.configData.typeBind) ? getTypeBindRelations(this.configData.typeBind,
this.parserOptions.typeField) : null,
groupFactory: () => {
let model;
@@ -327,7 +323,7 @@ export abstract class FieldParser {
// If typeBind is configured
if (isNotEmpty(this.configData.typeBind)) {
- (controlModel as DsDynamicInputModel).typeBindRelations = this.getTypeBindRelations(this.configData.typeBind,
+ (controlModel as DsDynamicInputModel).typeBindRelations = getTypeBindRelations(this.configData.typeBind,
this.parserOptions.typeField);
}
@@ -356,38 +352,6 @@ export abstract class FieldParser {
);
}
- /**
- * Get the type bind values from the REST data for a specific field
- * The return value is any[] in the method signature but in reality it's
- * returning the 'relation' that'll be used for a dynamic matcher when filtering
- * fields in type bind, made up of a 'match' outcome (make this field visible), an 'operator'
- * (OR) and a 'when' condition (the bindValues array).
- * @param configuredTypeBindValues array of types from the submission definition (CONFIG_DATA)
- * @param typeField
- * @private
- * @return DynamicFormControlRelation[] array with one relation in it, for type bind matching to show a field
- */
- private getTypeBindRelations(configuredTypeBindValues: string[], typeField: string): DynamicFormControlRelation[] {
- const bindValues = [];
- configuredTypeBindValues.forEach((value) => {
- bindValues.push({
- id: typeField,
- value: value,
- });
- });
- // match: MATCH_VISIBLE means that if true, the field / component will be visible
- // operator: OR means that all the values in the 'when' condition will be compared with OR, not AND
- // when: the list of values to match against, in this case the list of strings from ...
- // Example: Field [x] will be VISIBLE if item type = book OR item type = book_part
- //
- // The opposing match value will be the dc.type for the workspace item
- return [{
- match: MATCH_VISIBLE,
- operator: OR_OPERATOR,
- when: bindValues,
- }];
- }
-
protected hasRegex() {
return hasValue(this.configData.input.regex);
}