diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index ec030c6e9..13fc999b2 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -401,7 +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.required=Missing required property. message.conflict=Conflict message.data-version-contention=Data Version Contention diff --git a/ui/src/app/schema-form/widget/select/select.component.ts b/ui/src/app/schema-form/widget/select/select.component.ts index 5c6a2b65d..d504f0384 100644 --- a/ui/src/app/schema-form/widget/select/select.component.ts +++ b/ui/src/app/schema-form/widget/select/select.component.ts @@ -1,17 +1,20 @@ -import { Component, AfterViewInit } from '@angular/core'; +import { Component, AfterViewInit, OnDestroy } from '@angular/core'; import { SelectWidget } from 'ngx-schema-form'; import { SchemaService } from '../../service/schema.service'; -import { map, shareReplay } from 'rxjs/operators'; +import { map, shareReplay, startWith } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; @Component({ selector: 'select-component', templateUrl: `./select.component.html` }) -export class CustomSelectComponent extends SelectWidget implements AfterViewInit { +export class CustomSelectComponent extends SelectWidget implements AfterViewInit, OnDestroy { options$: any; + errorSub: Subscription; + constructor( private widgetService: SchemaService ) { @@ -38,6 +41,16 @@ export class CustomSelectComponent extends SelectWidget implements AfterViewInit ) ); } + + 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 { 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 95d19c2bc..6b6d16ae3 100644 --- a/ui/src/app/schema-form/widget/string/string.component.ts +++ b/ui/src/app/schema-form/widget/string/string.component.ts @@ -23,7 +23,7 @@ export class CustomStringComponent extends StringWidget implements AfterViewInit 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)) { + if (!v && this.required && !this.errorMessages.some(msg => !!msg.toLowerCase().match('required').length)) { this.errorMessages.push('message.required'); } }); diff --git a/ui/src/app/schema-form/widget/textarea/textarea.component.html b/ui/src/app/schema-form/widget/textarea/textarea.component.html index fb8164600..3705c4009 100644 --- a/ui/src/app/schema-form/widget/textarea/textarea.component.html +++ b/ui/src/app/schema-form/widget/textarea/textarea.component.html @@ -18,4 +18,10 @@ [rows]="schema.widget.rows || 5" [formControl]="control" [attr.aria-label]="schema.title"> + + + , + error + + diff --git a/ui/src/app/schema-form/widget/textarea/textarea.component.ts b/ui/src/app/schema-form/widget/textarea/textarea.component.ts index 0f68e524f..81d940bde 100644 --- a/ui/src/app/schema-form/widget/textarea/textarea.component.ts +++ b/ui/src/app/schema-form/widget/textarea/textarea.component.ts @@ -1,19 +1,37 @@ -import { Component } from '@angular/core'; +import { Component, AfterViewInit, OnDestroy } from '@angular/core'; import { TextAreaWidget } from 'ngx-schema-form'; import { SchemaService } from '../../service/schema.service'; +import { Subscription } from 'rxjs'; +import { startWith } from 'rxjs/operators'; @Component({ selector: 'textarea-component', templateUrl: `./textarea.component.html` }) -export class CustomTextAreaComponent extends TextAreaWidget { +export class CustomTextAreaComponent extends TextAreaWidget implements AfterViewInit, OnDestroy { + + errorSub: Subscription; + constructor( private widgetService: SchemaService ) { 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); }