mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-11 03:53:02 +00:00
Merge pull request #2133 from alexandrevryghem/fix-missing-hints-and-required-attributes-main
Fix missing hints and error messages for input-type `list` & `tag`
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
<ng-container #componentViewContainer></ng-container>
|
<ng-container #componentViewContainer></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<small *ngIf="hasHint && ((!model.repeatable && (isRelationship === false || value?.value === null)) || (model.repeatable === true && context?.index === context?.context?.groups?.length - 1)) && (!showErrorMessages || errorMessages.length === 0)"
|
<small *ngIf="hasHint && (formBuilderService.hasArrayGroupValue(model) || (!model.repeatable && (isRelationship === false || value?.value === null)) || (model.repeatable === true && context?.index === context?.context?.groups?.length - 1)) && (!showErrorMessages || errorMessages.length === 0)"
|
||||||
class="text-muted ds-hint" [innerHTML]="model.hint | translate" [ngClass]="getClass('element', 'hint')"></small>
|
class="text-muted ds-hint" [innerHTML]="model.hint | translate" [ngClass]="getClass('element', 'hint')"></small>
|
||||||
<!-- In case of repeatable fields show empty space for all elements except the first -->
|
<!-- In case of repeatable fields show empty space for all elements except the first -->
|
||||||
<div *ngIf="context?.index !== null
|
<div *ngIf="context?.index !== null
|
||||||
|
@@ -147,12 +147,14 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
|
|||||||
new DynamicListCheckboxGroupModel({
|
new DynamicListCheckboxGroupModel({
|
||||||
id: 'checkboxList',
|
id: 'checkboxList',
|
||||||
vocabularyOptions: vocabularyOptions,
|
vocabularyOptions: vocabularyOptions,
|
||||||
repeatable: true
|
repeatable: true,
|
||||||
|
required: false,
|
||||||
}),
|
}),
|
||||||
new DynamicListRadioGroupModel({
|
new DynamicListRadioGroupModel({
|
||||||
id: 'radioList',
|
id: 'radioList',
|
||||||
vocabularyOptions: vocabularyOptions,
|
vocabularyOptions: vocabularyOptions,
|
||||||
repeatable: false
|
repeatable: false,
|
||||||
|
required: false,
|
||||||
}),
|
}),
|
||||||
new DynamicRelationGroupModel({
|
new DynamicRelationGroupModel({
|
||||||
submissionId: '1234',
|
submissionId: '1234',
|
||||||
|
@@ -259,7 +259,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
|||||||
private submissionObjectService: SubmissionObjectDataService,
|
private submissionObjectService: SubmissionObjectDataService,
|
||||||
private ref: ChangeDetectorRef,
|
private ref: ChangeDetectorRef,
|
||||||
private formService: FormService,
|
private formService: FormService,
|
||||||
private formBuilderService: FormBuilderService,
|
public formBuilderService: FormBuilderService,
|
||||||
private submissionService: SubmissionService,
|
private submissionService: SubmissionService,
|
||||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||||
) {
|
) {
|
||||||
|
@@ -15,8 +15,10 @@ export interface DynamicListCheckboxGroupModelConfig extends DynamicFormGroupMod
|
|||||||
vocabularyOptions: VocabularyOptions;
|
vocabularyOptions: VocabularyOptions;
|
||||||
groupLength?: number;
|
groupLength?: number;
|
||||||
repeatable: boolean;
|
repeatable: boolean;
|
||||||
value?: any;
|
value?: VocabularyEntry[];
|
||||||
typeBindRelations?: DynamicFormControlRelation[];
|
typeBindRelations?: DynamicFormControlRelation[];
|
||||||
|
required: boolean;
|
||||||
|
hint?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
|
export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
|
||||||
@@ -26,6 +28,8 @@ export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
|
|||||||
@serializable() groupLength: number;
|
@serializable() groupLength: number;
|
||||||
@serializable() _value: VocabularyEntry[];
|
@serializable() _value: VocabularyEntry[];
|
||||||
@serializable() typeBindRelations: DynamicFormControlRelation[];
|
@serializable() typeBindRelations: DynamicFormControlRelation[];
|
||||||
|
@serializable() required: boolean;
|
||||||
|
@serializable() hint: string;
|
||||||
isListGroup = true;
|
isListGroup = true;
|
||||||
valueUpdates: Subject<any>;
|
valueUpdates: Subject<any>;
|
||||||
|
|
||||||
@@ -36,6 +40,8 @@ export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
|
|||||||
this.groupLength = config.groupLength || 5;
|
this.groupLength = config.groupLength || 5;
|
||||||
this._value = [];
|
this._value = [];
|
||||||
this.repeatable = config.repeatable;
|
this.repeatable = config.repeatable;
|
||||||
|
this.required = config.required;
|
||||||
|
this.hint = config.hint;
|
||||||
|
|
||||||
this.valueUpdates = new Subject<any>();
|
this.valueUpdates = new Subject<any>();
|
||||||
this.valueUpdates.subscribe((value: VocabularyEntry | VocabularyEntry[]) => this.value = value);
|
this.valueUpdates.subscribe((value: VocabularyEntry | VocabularyEntry[]) => this.value = value);
|
||||||
@@ -56,9 +62,8 @@ export class DynamicListCheckboxGroupModel extends DynamicCheckboxGroupModel {
|
|||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
} else {
|
} else {
|
||||||
// _value is non extendible so assign it a new array
|
// _value is non-extendable so assign it a new array
|
||||||
const newValue = (this.value as VocabularyEntry[]).concat([value]);
|
this._value = (this.value as VocabularyEntry[]).concat([value]);
|
||||||
this._value = newValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,12 +6,15 @@ import {
|
|||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../../../../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { hasValue } from '../../../../../empty.util';
|
import { hasValue } from '../../../../../empty.util';
|
||||||
|
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
|
|
||||||
export interface DynamicListModelConfig extends DynamicRadioGroupModelConfig<any> {
|
export interface DynamicListModelConfig extends DynamicRadioGroupModelConfig<any> {
|
||||||
vocabularyOptions: VocabularyOptions;
|
vocabularyOptions: VocabularyOptions;
|
||||||
groupLength?: number;
|
groupLength?: number;
|
||||||
repeatable: boolean;
|
repeatable: boolean;
|
||||||
value?: any;
|
value?: VocabularyEntry[];
|
||||||
|
required: boolean;
|
||||||
|
hint?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DynamicListRadioGroupModel extends DynamicRadioGroupModel<any> {
|
export class DynamicListRadioGroupModel extends DynamicRadioGroupModel<any> {
|
||||||
@@ -19,6 +22,8 @@ export class DynamicListRadioGroupModel extends DynamicRadioGroupModel<any> {
|
|||||||
@serializable() vocabularyOptions: VocabularyOptions;
|
@serializable() vocabularyOptions: VocabularyOptions;
|
||||||
@serializable() repeatable: boolean;
|
@serializable() repeatable: boolean;
|
||||||
@serializable() groupLength: number;
|
@serializable() groupLength: number;
|
||||||
|
@serializable() required: boolean;
|
||||||
|
@serializable() hint: string;
|
||||||
isListGroup = true;
|
isListGroup = true;
|
||||||
|
|
||||||
constructor(config: DynamicListModelConfig, layout?: DynamicFormControlLayout) {
|
constructor(config: DynamicListModelConfig, layout?: DynamicFormControlLayout) {
|
||||||
@@ -27,6 +32,8 @@ export class DynamicListRadioGroupModel extends DynamicRadioGroupModel<any> {
|
|||||||
this.vocabularyOptions = config.vocabularyOptions;
|
this.vocabularyOptions = config.vocabularyOptions;
|
||||||
this.groupLength = config.groupLength || 5;
|
this.groupLength = config.groupLength || 5;
|
||||||
this.repeatable = config.repeatable;
|
this.repeatable = config.repeatable;
|
||||||
|
this.required = config.required;
|
||||||
|
this.hint = config.hint;
|
||||||
this.value = config.value;
|
this.value = config.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
[id]="item.id"
|
[id]="item.id"
|
||||||
[formControlName]="item.id"
|
[formControlName]="item.id"
|
||||||
[name]="model.name"
|
[name]="model.name"
|
||||||
[required]="model.required"
|
|
||||||
[value]="item.value"
|
[value]="item.value"
|
||||||
(blur)="onBlur($event)"
|
(blur)="onBlur($event)"
|
||||||
(change)="onChange($event)"
|
(change)="onChange($event)"
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup, ValidatorFn, ValidationErrors, AbstractControl } from '@angular/forms';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DynamicCheckboxModel,
|
DynamicCheckboxModel,
|
||||||
DynamicFormControlComponent,
|
DynamicFormControlComponent,
|
||||||
@@ -110,6 +109,9 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
|
|||||||
protected setOptionsFromVocabulary() {
|
protected setOptionsFromVocabulary() {
|
||||||
if (this.model.vocabularyOptions.name && this.model.vocabularyOptions.name.length > 0) {
|
if (this.model.vocabularyOptions.name && this.model.vocabularyOptions.name.length > 0) {
|
||||||
const listGroup = this.group.controls[this.model.id] as FormGroup;
|
const listGroup = this.group.controls[this.model.id] as FormGroup;
|
||||||
|
if (this.model.repeatable && this.model.required) {
|
||||||
|
listGroup.addValidators(this.hasAtLeastOneVocabularyEntry());
|
||||||
|
}
|
||||||
const pageInfo: PageInfo = new PageInfo({
|
const pageInfo: PageInfo = new PageInfo({
|
||||||
elementsPerPage: 9999, currentPage: 1
|
elementsPerPage: 9999, currentPage: 1
|
||||||
} as PageInfo);
|
} as PageInfo);
|
||||||
@@ -121,7 +123,7 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
|
|||||||
let tempList: ListItem[] = [];
|
let tempList: ListItem[] = [];
|
||||||
this.optionsList = entries.page;
|
this.optionsList = entries.page;
|
||||||
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
|
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
|
||||||
entries.page.forEach((option, key) => {
|
entries.page.forEach((option: VocabularyEntry, key: number) => {
|
||||||
const value = option.authority || option.value;
|
const value = option.authority || option.value;
|
||||||
const checked: boolean = isNotEmpty(findKey(
|
const checked: boolean = isNotEmpty(findKey(
|
||||||
this.model.value,
|
this.model.value,
|
||||||
@@ -156,4 +158,13 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if at least one {@link VocabularyEntry} has been selected.
|
||||||
|
*/
|
||||||
|
hasAtLeastOneVocabularyEntry(): ValidatorFn {
|
||||||
|
return (control: AbstractControl): ValidationErrors | null => {
|
||||||
|
return control && control.value && Object.values(control.value).find((checked: boolean) => checked === true) ? null : this.model.errorMessages;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -235,10 +235,16 @@ describe('FormBuilderService test suite', () => {
|
|||||||
new DynamicListCheckboxGroupModel({
|
new DynamicListCheckboxGroupModel({
|
||||||
id: 'testCheckboxList',
|
id: 'testCheckboxList',
|
||||||
vocabularyOptions: vocabularyOptions,
|
vocabularyOptions: vocabularyOptions,
|
||||||
repeatable: true
|
repeatable: true,
|
||||||
|
required: false,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new DynamicListRadioGroupModel({ id: 'testRadioList', vocabularyOptions: vocabularyOptions, repeatable: false }),
|
new DynamicListRadioGroupModel({
|
||||||
|
id: 'testRadioList',
|
||||||
|
vocabularyOptions: vocabularyOptions,
|
||||||
|
repeatable: false,
|
||||||
|
required: false,
|
||||||
|
}),
|
||||||
|
|
||||||
new DynamicRelationGroupModel({
|
new DynamicRelationGroupModel({
|
||||||
submissionId,
|
submissionId,
|
||||||
|
Reference in New Issue
Block a user