diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index 1c207ee38..ec030c6e9 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -401,6 +401,7 @@ message.org-incomplete=These three fields must all be entered if any single fiel message.type-required=Missing required property: Type message.match-required=Missing required property: Match message.value-required=Missing required property: Value +message.required=Field is required. message.conflict=Conflict message.data-version-contention=Data Version Contention diff --git a/ui/src/app/metadata/domain/model/wizards/metadata-source-base.ts b/ui/src/app/metadata/domain/model/wizards/metadata-source-base.ts index ebc8921d8..673f176c1 100644 --- a/ui/src/app/metadata/domain/model/wizards/metadata-source-base.ts +++ b/ui/src/app/metadata/domain/model/wizards/metadata-source-base.ts @@ -60,6 +60,28 @@ export class MetadataSourceBase implements Wizard { } getValidators(entityIdList: string[]): { [key: string]: any } { + const checkRequiredChild = (value, property, form) => { + if (!value) { + return { + code: 'REQUIRED', + path: `#${property.path}`, + message: `message.required`, + params: [value] + }; + } + return null; + }; + const checkRequiredChildren = (value, property, form) => { + let errors; + Object.keys(value).forEach((item, index, all) => { + const error = checkRequiredChild(item, { path: `${index}` }, form); + if (error) { + errors = errors || []; + errors.push(error); + } + }); + return errors; + }; const checkOrg = (value, property, form) => { const org = property.parent; const orgValue = org.value || {}; diff --git a/ui/src/app/schema-form/widget/string/string.component.ts b/ui/src/app/schema-form/widget/string/string.component.ts index 2de93e371..95d19c2bc 100644 --- a/ui/src/app/schema-form/widget/string/string.component.ts +++ b/ui/src/app/schema-form/widget/string/string.component.ts @@ -1,14 +1,18 @@ -import { Component } from '@angular/core'; +import { Component, AfterViewInit, OnDestroy } from '@angular/core'; import { StringWidget } from 'ngx-schema-form'; import { Validators } from '@angular/forms'; import { SchemaService } from '../../service/schema.service'; +import { startWith } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; @Component({ selector: 'custom-string', templateUrl: `./string.component.html`, styleUrls: ['../widget.component.scss'] }) -export class CustomStringComponent extends StringWidget { +export class CustomStringComponent extends StringWidget implements AfterViewInit, OnDestroy { + + errorSub: Subscription; constructor( private widgetService: SchemaService @@ -16,7 +20,22 @@ export class CustomStringComponent extends StringWidget { super(); } + ngAfterViewInit(): void { + super.ngAfterViewInit(); + this.errorSub = this.control.valueChanges.pipe(startWith(this.control.value)).subscribe(v => { + if (!v && this.required && this.errorMessages.some(msg => !!msg.toLowerCase().match('required').length)) { + this.errorMessages.push('message.required'); + } + }); + } + + ngOnDestroy(): void { + this.errorSub.unsubscribe(); + } + get required(): boolean { - return this.widgetService.isRequired(this.formProperty); + const req = this.widgetService.isRequired(this.formProperty); + + return req; } }