mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 02:24:11 +00:00
updated with latest changes
This commit is contained in:
@@ -288,6 +288,7 @@
|
||||
<ds-dynamic-group [model]="model"
|
||||
[formId]="formId"
|
||||
[group]="group"
|
||||
[showErrorMessages]="showErrorMessages"
|
||||
(blur)="onBlur($event)"
|
||||
(change)="onValueChange($event)"
|
||||
(focus)="onFocus($event)"></ds-dynamic-group>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
[value]="year"
|
||||
[invalid]="showErrorMessages"
|
||||
[placeholder]='yearPlaceholder'
|
||||
(blur)="onBlur($event)"
|
||||
(change)="onChange($event)"
|
||||
(focus)="onFocus($event)"
|
||||
></ds-number-picker>
|
||||
@@ -24,6 +25,7 @@
|
||||
[value]="month"
|
||||
[placeholder]="monthPlaceholder"
|
||||
[disabled]="!year || model.disabled"
|
||||
(blur)="onBlur($event)"
|
||||
(change)="onChange($event)"
|
||||
(focus)="onFocus($event)"
|
||||
></ds-number-picker>
|
||||
@@ -38,6 +40,7 @@
|
||||
[value]="day"
|
||||
[placeholder]="dayPlaceholder"
|
||||
[disabled]="!month || model.disabled"
|
||||
(blur)="onBlur($event)"
|
||||
(change)="onChange($event)"
|
||||
(focus)="onFocus($event)"
|
||||
></ds-number-picker>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { DynamicDsDatePickerModel } from './date-picker.model';
|
||||
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
||||
|
||||
@@ -23,6 +23,7 @@ export class DsDatePickerComponent implements OnInit {
|
||||
|
||||
@Output() selected = new EventEmitter<number>();
|
||||
@Output() remove = new EventEmitter<number>();
|
||||
@Output() blur = new EventEmitter<any>();
|
||||
@Output() change = new EventEmitter<any>();
|
||||
@Output() focus = new EventEmitter<any>();
|
||||
|
||||
@@ -76,6 +77,10 @@ export class DsDatePickerComponent implements OnInit {
|
||||
|
||||
}
|
||||
|
||||
onBlur(event) {
|
||||
this.blur.emit();
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
// update year-month-day
|
||||
switch (event.field) {
|
||||
|
@@ -15,14 +15,16 @@
|
||||
(click)="expandForm()"></span>
|
||||
</a>
|
||||
|
||||
<div class="pt-2" [ngClass]="{'border-top': !invalid, 'border border-danger': invalid}">
|
||||
<div class="pt-2" [ngClass]="{'border-top': !showErrorMessages, 'border border-danger': showErrorMessages}">
|
||||
<div *ngIf="!(formCollapsed | async)" class="pl-2 row" @shrinkInOut>
|
||||
<ds-form #formRef="formComponent"
|
||||
class="col-sm-12 col-md-8 col-lg-9 col-xl-10 pl-0"
|
||||
[formId]="formId"
|
||||
[formModel]="formModel"
|
||||
[displaySubmit]="false"
|
||||
(dfChange)="onChange($event)"></ds-form>
|
||||
[emitChange]="false"
|
||||
(dfBlur)="onBlur($event)"
|
||||
(dfFocus)="onFocus($event)"></ds-form>
|
||||
|
||||
|
||||
<div *ngIf="!(formCollapsed | async)" class="col p-0 m-0 d-flex justify-content-center align-items-center">
|
||||
|
@@ -11,12 +11,7 @@ import {
|
||||
} from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import {
|
||||
DynamicFormControlEvent,
|
||||
DynamicFormControlModel,
|
||||
DynamicFormGroupModel,
|
||||
DynamicInputModel
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import { DynamicGroupModel, PLACEHOLDER_PARENT_METADATA } from './dynamic-group.model';
|
||||
@@ -25,7 +20,6 @@ import { SubmissionFormsModel } from '../../../../../../core/shared/config/confi
|
||||
import { FormService } from '../../../../form.service';
|
||||
import { FormComponent } from '../../../../form.component';
|
||||
import { Chips } from '../../../../../chips/models/chips.model';
|
||||
import { DynamicLookupModel } from '../lookup/dynamic-lookup.model';
|
||||
import { hasValue, isEmpty, isNotEmpty } from '../../../../../empty.util';
|
||||
import { shrinkInOut } from '../../../../../animations/shrink';
|
||||
import { ChipsItem } from '../../../../../chips/models/chips-item.model';
|
||||
@@ -48,6 +42,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
@Input() formId: string;
|
||||
@Input() group: FormGroup;
|
||||
@Input() model: DynamicGroupModel;
|
||||
@Input() showErrorMessages = false;
|
||||
|
||||
@Output() blur: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() change: EventEmitter<any> = new EventEmitter<any>();
|
||||
@@ -57,7 +52,6 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
public formCollapsed = Observable.of(false);
|
||||
public formModel: DynamicFormControlModel[];
|
||||
public editMode = false;
|
||||
public invalid = false;
|
||||
|
||||
private selectedChipItem: ChipsItem;
|
||||
private subs: Subscription[] = [];
|
||||
@@ -72,7 +66,7 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
const config = {rows: this.model.formConfiguration} as SubmissionFormsModel;
|
||||
if (isNotEmpty(this.model.value)) {
|
||||
if (!this.model.isEmpty()) {
|
||||
this.formCollapsed = Observable.of(true);
|
||||
}
|
||||
this.model.valueUpdates.subscribe((value: any[]) => {
|
||||
@@ -80,38 +74,22 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
|
||||
this.formId = this.formService.getUniqueId(this.model.id);
|
||||
this.formModel = this.formBuilderService.modelFromConfiguration(config, this.model.scopeUUID, {});
|
||||
this.chips = new Chips(this.model.value, 'value', this.model.mandatoryField);
|
||||
this.formModel = this.formBuilderService.modelFromConfiguration(config, this.model.scopeUUID, {}, this.model.submissionScope, this.model.readOnly);
|
||||
const initChipsValue = this.model.isEmpty() ? [] : this.model.value;
|
||||
this.chips = new Chips(initChipsValue, 'value', this.model.mandatoryField);
|
||||
this.subs.push(
|
||||
this.chips.chipsItems
|
||||
.subscribe((subItems: any[]) => {
|
||||
const items = this.chips.getChipsItems();
|
||||
// Does not emit change if model value is equal to the current value
|
||||
if (!isEqual(items, this.model.value)) {
|
||||
if (isEmpty(items)) {
|
||||
// If items is empty, last element has been removed
|
||||
// so emit an empty value that allows to dispatch
|
||||
// a remove JSON PATCH operation
|
||||
const emptyItem = Object.create({});
|
||||
Object.keys(this.model.value[0])
|
||||
.forEach((key) => {
|
||||
emptyItem[key] = null;
|
||||
});
|
||||
items.push(emptyItem);
|
||||
// if ((isNotEmpty(items) && !this.model.isEmpty()) || (isEmpty(items) && !this.model.isEmpty())) {
|
||||
if (!(isEmpty(items) && this.model.isEmpty())) {
|
||||
this.model.valueUpdates.next(items);
|
||||
this.change.emit();
|
||||
}
|
||||
|
||||
this.model.valueUpdates.next(items);
|
||||
this.change.emit();
|
||||
}
|
||||
}),
|
||||
// Invalid state for year
|
||||
this.group.get(this.model.id).statusChanges.subscribe((state) => {
|
||||
if (state === 'INVALID') {
|
||||
this.invalid = true;
|
||||
} else {
|
||||
this.invalid = false;
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,8 +108,8 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
return res;
|
||||
}
|
||||
|
||||
onChange(event: DynamicFormControlEvent) {
|
||||
return
|
||||
onBlur(event) {
|
||||
this.blur.emit();
|
||||
}
|
||||
|
||||
onChipSelected(event) {
|
||||
@@ -142,26 +120,23 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
modelRow.group.forEach((model: DynamicInputModel) => {
|
||||
const value = (this.selectedChipItem.item[model.name] === PLACEHOLDER_PARENT_METADATA
|
||||
|| this.selectedChipItem.item[model.name].value === PLACEHOLDER_PARENT_METADATA)
|
||||
? null
|
||||
: this.selectedChipItem.item[model.name];
|
||||
? null
|
||||
: this.selectedChipItem.item[model.name];
|
||||
if (value instanceof FormFieldMetadataValueObject || value instanceof AuthorityValueModel) {
|
||||
model.valueUpdates.next(value.display);
|
||||
} else {
|
||||
model.valueUpdates.next(value);
|
||||
}
|
||||
// if (model instanceof DynamicLookupModel) {
|
||||
// (model as DynamicLookupModel).valueUpdates.next(value);
|
||||
// } else if (model instanceof DynamicInputModel) {
|
||||
// model.valueUpdates.next(value);
|
||||
// } else {
|
||||
// (model as any).value = value;
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
this.editMode = true;
|
||||
}
|
||||
|
||||
onFocus(event) {
|
||||
this.focus.emit(event);
|
||||
}
|
||||
|
||||
collapseForm() {
|
||||
this.formCollapsed = Observable.of(true);
|
||||
this.clear();
|
||||
@@ -178,7 +153,9 @@ export class DsDynamicGroupComponent implements OnDestroy, OnInit {
|
||||
this.editMode = false;
|
||||
}
|
||||
this.resetForm();
|
||||
// this.change.emit(event);
|
||||
if (!this.model.isEmpty()) {
|
||||
this.formCollapsed = Observable.of(true);
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import { DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core';
|
||||
import { FormRowModel } from '../../../../../../core/shared/config/config-submission-forms.model';
|
||||
import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-input.model';
|
||||
import { AuthorityValueModel } from '../../../../../../core/integration/models/authority-value.model';
|
||||
import { isEmpty, isNull } from '../../../../../empty.util';
|
||||
|
||||
export const DYNAMIC_FORM_CONTROL_TYPE_RELATION = 'RELATION';
|
||||
export const PLACEHOLDER_PARENT_METADATA = '#PLACEHOLDER_PARENT_METADATA_VALUE#';
|
||||
@@ -14,6 +16,7 @@ export interface DynamicGroupModelConfig extends DsDynamicInputModelConfig {
|
||||
name: string,
|
||||
relationFields: string[],
|
||||
scopeUUID: string,
|
||||
submissionScope: string;
|
||||
value?: any;
|
||||
}
|
||||
|
||||
@@ -25,7 +28,8 @@ export class DynamicGroupModel extends DsDynamicInputModel {
|
||||
@serializable() mandatoryField: string;
|
||||
@serializable() relationFields: string[];
|
||||
@serializable() scopeUUID: string;
|
||||
@serializable() value: any[];
|
||||
@serializable() submissionScope: string;
|
||||
@serializable() _value: any[];
|
||||
@serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_RELATION;
|
||||
|
||||
constructor(config: DynamicGroupModelConfig, layout?: DynamicFormControlLayout) {
|
||||
@@ -35,7 +39,32 @@ export class DynamicGroupModel extends DsDynamicInputModel {
|
||||
this.mandatoryField = config.mandatoryField;
|
||||
this.relationFields = config.relationFields;
|
||||
this.scopeUUID = config.scopeUUID;
|
||||
this.submissionScope = config.submissionScope;
|
||||
const value = config.value || [];
|
||||
this.valueUpdates.next(value)
|
||||
this.valueUpdates.next(value);
|
||||
}
|
||||
|
||||
get value() {
|
||||
if (isEmpty(this._value)) {
|
||||
// If items is empty, last element has been removed
|
||||
// so emit an empty value that allows to dispatch
|
||||
// a remove JSON PATCH operation
|
||||
const emptyItem = Object.create({});
|
||||
emptyItem[this.mandatoryField] = null;
|
||||
this.relationFields
|
||||
.forEach((field) => {
|
||||
emptyItem[field] = null;
|
||||
});
|
||||
return [emptyItem];
|
||||
}
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value(value) {
|
||||
this._value = value;
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return (this.value.length === 1 && isNull(this.value[0][this.mandatoryField]));
|
||||
}
|
||||
}
|
||||
|
@@ -162,12 +162,13 @@ export class FormBuilderService extends DynamicFormService {
|
||||
Object.keys(groupValue)
|
||||
.forEach((key) => {
|
||||
const normValue = normalizeValue(controlModel, groupValue[key], groupIndex);
|
||||
if (iterateResult.hasOwnProperty(key)) {
|
||||
iterateResult[key].push(normValue);
|
||||
} else {
|
||||
iterateResult[key] = [normValue];
|
||||
if (normValue.hasValue()) {
|
||||
if (iterateResult.hasOwnProperty(key)) {
|
||||
iterateResult[key].push(normValue);
|
||||
} else {
|
||||
iterateResult[key] = [normValue];
|
||||
}
|
||||
}
|
||||
// newGroupValue[key] = normalizeValue(controlModel, groupValue[key], groupIndex);
|
||||
});
|
||||
// controlArrayValue.push(newGroupValue);
|
||||
})
|
||||
|
@@ -13,7 +13,8 @@ export class GroupFieldParser extends FieldParser {
|
||||
constructor(protected configData: FormFieldModel,
|
||||
protected initFormValues,
|
||||
protected readOnly: boolean,
|
||||
protected authorityUuid: string) {
|
||||
protected submissionScope: string,
|
||||
protected authorityUuid: string,) {
|
||||
super(configData, initFormValues, readOnly);
|
||||
}
|
||||
|
||||
@@ -21,6 +22,7 @@ export class GroupFieldParser extends FieldParser {
|
||||
const modelConfiguration: DynamicGroupModelConfig = this.initModel();
|
||||
|
||||
modelConfiguration.scopeUUID = this.authorityUuid;
|
||||
modelConfiguration.submissionScope = this.submissionScope;
|
||||
if (this.configData && this.configData.rows && this.configData.rows.length > 0) {
|
||||
modelConfiguration.formConfiguration = this.configData.rows;
|
||||
modelConfiguration.relationFields = [];
|
||||
|
@@ -90,7 +90,7 @@ export class RowParser {
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
fieldModel = new GroupFieldParser(fieldData, this.initFormValues, this.readOnly, this.authorityOptions.uuid).parse();
|
||||
fieldModel = new GroupFieldParser(fieldData, this.initFormValues, this.readOnly, this.submissionScope, this.authorityOptions.uuid).parse();
|
||||
break;
|
||||
|
||||
case 'twobox':
|
||||
|
@@ -6,6 +6,7 @@
|
||||
[formGroup]="formGroup"
|
||||
[formModel]="formModel"
|
||||
[formLayout]="formLayout"
|
||||
(change)="$event.stopPropagation();"
|
||||
(dfBlur)="onBlur($event)"
|
||||
(dfChange)="onChange($event)"
|
||||
(dfFocus)="onFocus($event)">
|
||||
|
@@ -8,6 +8,7 @@ import {
|
||||
DynamicFormGroupModel, DynamicFormLayout,
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { findIndex } from 'lodash';
|
||||
|
||||
import { AppState } from '../../app.reducer';
|
||||
import {
|
||||
@@ -37,6 +38,7 @@ import { isEmpty } from 'lodash';
|
||||
})
|
||||
export class FormComponent implements OnDestroy, OnInit {
|
||||
|
||||
private formErrors: FormError[] = [];
|
||||
private formValid: boolean;
|
||||
|
||||
/**
|
||||
@@ -44,6 +46,11 @@ export class FormComponent implements OnDestroy, OnInit {
|
||||
*/
|
||||
@Input() displaySubmit = true;
|
||||
|
||||
/**
|
||||
* A boolean that indicate if to emit a form change event
|
||||
*/
|
||||
@Input() emitChange = true;
|
||||
|
||||
/**
|
||||
* The form unique ID
|
||||
*/
|
||||
@@ -154,7 +161,9 @@ export class FormComponent implements OnDestroy, OnInit {
|
||||
.subscribe((errors: FormError[]) => {
|
||||
const {formGroup, formModel} = this;
|
||||
|
||||
errors.forEach((error: FormError) => {
|
||||
errors
|
||||
.filter((error: FormError) => findIndex(this.formErrors, {fieldId: error.fieldId}) === -1)
|
||||
.forEach((error: FormError) => {
|
||||
const {fieldId} = error;
|
||||
let field: AbstractControl;
|
||||
if (!!this.parentFormModel) {
|
||||
@@ -166,9 +175,29 @@ export class FormComponent implements OnDestroy, OnInit {
|
||||
if (field) {
|
||||
const model: DynamicFormControlModel = this.formBuilderService.findById(fieldId, formModel);
|
||||
this.formService.addErrorToField(field, model, error.message);
|
||||
// this.formService.validateAllFormFields(formGroup);
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
});
|
||||
|
||||
this.formErrors
|
||||
.filter((error: FormError) => findIndex(errors, {fieldId: error.fieldId}) === -1)
|
||||
.forEach((error: FormError) => {
|
||||
const {fieldId} = error;
|
||||
let field: AbstractControl;
|
||||
if (!!this.parentFormModel) {
|
||||
field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel);
|
||||
} else {
|
||||
field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel);
|
||||
}
|
||||
|
||||
if (field) {
|
||||
const model: DynamicFormControlModel = this.formBuilderService.findById(fieldId, formModel);
|
||||
this.formService.removeErrorFromField(field, model, error.message);
|
||||
}
|
||||
});
|
||||
|
||||
this.formErrors = errors;
|
||||
this.changeDetectorRef.detectChanges();
|
||||
})
|
||||
);
|
||||
@@ -217,10 +246,11 @@ export class FormComponent implements OnDestroy, OnInit {
|
||||
this.store.dispatch(action);
|
||||
this.formGroup.markAsPristine();
|
||||
|
||||
this.change.emit(event);
|
||||
const control: FormControl = event.control;
|
||||
if (this.emitChange) {
|
||||
this.change.emit(event);
|
||||
}
|
||||
|
||||
// control.setErrors(null);
|
||||
const control: FormControl = event.control;
|
||||
if (control.valid) {
|
||||
this.store.dispatch(new FormRemoveErrorAction(this.formId, event.model.id));
|
||||
}
|
||||
|
@@ -7,9 +7,9 @@ import { AppState } from '../../app.reducer';
|
||||
import { formObjectFromIdSelector } from './selectors';
|
||||
import { FormBuilderService } from './builder/form-builder.service';
|
||||
import { DynamicFormControlModel, DynamicFormGroupModel } from '@ng-dynamic-forms/core';
|
||||
import { isNotEmpty, isNotUndefined } from '../empty.util';
|
||||
import { isEmpty, isNotEmpty, isNotUndefined } from '../empty.util';
|
||||
import { find, uniqueId } from 'lodash';
|
||||
import { FormChangeAction } from './form.actions';
|
||||
import { FormChangeAction, FormRemoveErrorAction } from './form.actions';
|
||||
|
||||
@Injectable()
|
||||
export class FormService {
|
||||
@@ -75,39 +75,46 @@ export class FormService {
|
||||
}
|
||||
|
||||
public addErrorToField(field: AbstractControl, model: DynamicFormControlModel, message: string) {
|
||||
const errorFound = !!(find(field.errors, (err) => err === message));
|
||||
|
||||
// search for the same error in the formControl.errors property
|
||||
if (!errorFound) {
|
||||
const errorKey = uniqueId('error-'); // create a single key for the error
|
||||
const error = {}; // create the error object
|
||||
const error = {}; // create the error object
|
||||
|
||||
error[errorKey] = message; // assign message
|
||||
|
||||
// if form control model has not errorMessages object, create it
|
||||
if (!model.errorMessages) {
|
||||
model.errorMessages = {};
|
||||
}
|
||||
|
||||
// put the error in the form control model
|
||||
model.errorMessages[errorKey] = message;
|
||||
|
||||
// Use correct error messages from the model
|
||||
const lastArray = message.split('.');
|
||||
if (lastArray && lastArray.length > 0) {
|
||||
const last = lastArray[lastArray.length - 1];
|
||||
const modelMsg = model.errorMessages[last];
|
||||
if (modelMsg && modelMsg.length > 0) {
|
||||
model.errorMessages[errorKey] = modelMsg;
|
||||
}
|
||||
}
|
||||
|
||||
// add the error in the form control
|
||||
field.setErrors(error);
|
||||
|
||||
// formGroup.markAsDirty();
|
||||
field.markAsTouched();
|
||||
// if form control model has not errorMessages object, create it
|
||||
if (!model.errorMessages) {
|
||||
model.errorMessages = {};
|
||||
}
|
||||
|
||||
// Use correct error messages from the model
|
||||
const lastArray = message.split('.');
|
||||
if (lastArray && lastArray.length > 0) {
|
||||
// check if error code is already present in the set of model's validators
|
||||
const last = lastArray[lastArray.length - 1];
|
||||
const modelMsg = model.errorMessages[last];
|
||||
if (isEmpty(modelMsg)) {
|
||||
const errorKey = uniqueId('error-'); // create a single key for the error
|
||||
error[errorKey] = true;
|
||||
// put the error message in the form control model
|
||||
model.errorMessages[errorKey] = message;
|
||||
} else {
|
||||
error[last] = modelMsg;
|
||||
}
|
||||
}
|
||||
|
||||
// add the error in the form control
|
||||
field.setErrors(error);
|
||||
field.markAsTouched();
|
||||
}
|
||||
|
||||
public removeErrorFromField(field: AbstractControl, model: DynamicFormControlModel, message) {
|
||||
const error = {};
|
||||
|
||||
// Use correct error messages from the model
|
||||
const lastArray = message.split('.');
|
||||
if (lastArray && lastArray.length > 0) {
|
||||
const last = lastArray[lastArray.length - 1];
|
||||
error[last] = null;
|
||||
}
|
||||
field.setErrors(error);
|
||||
field.markAsUntouched();
|
||||
}
|
||||
|
||||
public resetForm(formGroup: FormGroup, groupModel: DynamicFormControlModel[], formId: string) {
|
||||
|
Reference in New Issue
Block a user