fix issues with repeatable fields

This commit is contained in:
Art Lowel
2020-04-01 11:06:31 +02:00
parent a8d5ad9c37
commit 2989ca4d96
21 changed files with 156 additions and 72 deletions

View File

@@ -7,10 +7,10 @@
[ngClass]="[getClass('element', 'label'), getClass('grid', 'label')]"></label>
<ng-container *ngTemplateOutlet="startTemplate?.templateRef; context: model"></ng-container>
<!-- Should be *ngIf instead of class d-none, but that breaks the #componentViewContainer reference-->
<div [ngClass]="{'form-row': model.hasLanguages || isRelationship, 'd-none': relationshipValue$ | async}">
<div [ngClass]="{'form-row': model.hasLanguages || isRelationship, 'd-none': value?.isVirtual}">
<div [ngClass]="getClass('grid', 'control')">
<ng-container #componentViewContainer></ng-container>
<small *ngIf="hasHint && (!showErrorMessages || errorMessages.length === 0)"
<small *ngIf="hasHint && context?.index === 0 && (!showErrorMessages || errorMessages.length === 0)"
class="text-muted" [innerHTML]="model.hint | translate" [ngClass]="getClass('element', 'hint')"></small>
<div *ngIf="showErrorMessages" [ngClass]="[getClass('element', 'errors'), getClass('grid', 'errors')]">

View File

@@ -33,7 +33,7 @@ import {
DynamicDatePickerModel, DynamicFormComponentService,
DynamicFormControl,
DynamicFormControlContainerComponent,
DynamicFormControlEvent,
DynamicFormControlEvent, DynamicFormControlEventType,
DynamicFormControlModel,
DynamicFormLayout,
DynamicFormLayoutService, DynamicFormRelationService,
@@ -60,7 +60,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/dat
import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP } from './models/lookup/dynamic-lookup.model';
import { DynamicListCheckboxGroupModel } from './models/list/dynamic-list-checkbox-group.model';
import { DynamicListRadioGroupModel } from './models/list/dynamic-list-radio-group.model';
import { hasNoValue, hasValue, isNotEmpty, isNotUndefined } from '../../../empty.util';
import { hasNoValue, hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../../empty.util';
import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_NAME } from './models/lookup/dynamic-lookup-name.model';
import { DsDynamicTagComponent } from './models/tag/dynamic-tag.component';
import { DsDatePickerComponent } from './models/date-picker/date-picker.component';
@@ -73,7 +73,7 @@ import { DsDynamicFormArrayComponent } from './models/array-group/dynamic-form-a
import { DsDynamicRelationGroupComponent } from './models/relation-group/dynamic-relation-group.components';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/relation-group/dynamic-relation-group.model';
import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component';
import { map, startWith, switchMap, find, take } from 'rxjs/operators';
import { map, startWith, switchMap, find, take, tap } from 'rxjs/operators';
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
import { SearchResult } from '../../../search/search-result.model';
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
@@ -246,7 +246,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload());
this.relationshipValue$ = observableCombineLatest(this.item$.pipe(take(1)), relationship$).pipe(
this.relationshipValue$ = observableCombineLatest([this.item$.pipe(take(1)), relationship$]).pipe(
switchMap(([item, relationship]: [Item, Relationship]) =>
relationship.leftItem.pipe(
getSucceededRemoteData(),
@@ -278,7 +278,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
}
ngOnChanges(changes: SimpleChanges) {
if (changes) {
if (changes && !this.isRelationship) {
super.ngOnChanges(changes);
if (this.model && this.model.placeholder) {
this.model.placeholder = this.translateService.instant(this.model.placeholder);
@@ -322,7 +322,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
* Open a modal where the user can select relationships to be added to item being submitted
*/
openLookup() {
this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, {
size: 'lg'
});
@@ -330,11 +329,14 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
modalComp.query = this.model.value ? this.model.value.value : '';
if (hasValue(this.model.value)) {
// this.model.reset();
// this.model.value = undefined;
// this.model.valueUpdates(undefined);
this.model.value.value = undefined;
this.change.emit();
this.model.value = '';
this.onChange({
$event: { previousIndex: 0 },
context: { index: 0 },
control: this.control,
model: this.model,
type: DynamicFormControlEventType.Change
});
}
this.submissionService.dispatchSave(this.model.submissionId);
@@ -368,5 +370,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
this.subs.push(this.item$.subscribe((item) => this.item = item));
this.subs.push(collection$.subscribe((collection) => this.collection = collection));
}
}

View File

@@ -1,10 +1,10 @@
<div class="d-flex">
<span class="mr-auto text-contents">
<ng-container *ngIf="!metadataRepresentation">
<ng-container *ngIf="!(metadataRepresentation$ | async)">
<ds-loading [showMessage]="false"></ds-loading>
</ng-container>
<ng-container *ngIf="metadataRepresentation">
<ds-metadata-representation-loader [mdRepresentation]="metadataRepresentation"></ds-metadata-representation-loader>
<ng-container *ngIf="(metadataRepresentation$ | async)">
<ds-metadata-representation-loader [mdRepresentation]="metadataRepresentation$ | async"></ds-metadata-representation-loader>
</ng-container>
</span>
<button type="button" class="btn btn-secondary"

View File

@@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, OnChanges, OnDestroy } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { DynamicFormArrayGroupModel, DynamicFormControlEvent } from '@ng-dynamic-forms/core';
import { Store } from '@ngrx/store';
import { Observable, of as observableOf, Subject, Subscription } from 'rxjs';
import { BehaviorSubject, Observable, of as observableOf, Subject, Subscription } from 'rxjs';
import { filter, switchMap } from 'rxjs/operators';
import { AppState } from '../../../../../app.reducer';
import { RelationshipService } from '../../../../../core/data/relationship.service';
@@ -140,7 +140,7 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro
@Input() metadataFields: string[];
@Input() relationshipOptions: RelationshipOptions;
@Input() submissionId: string;
metadataRepresentation: MetadataRepresentation;
metadataRepresentation$: BehaviorSubject<MetadataRepresentation>;
relatedItem: Item;
/**
@@ -167,10 +167,15 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro
const relationMD: MetadataValue = this.submissionItem.firstMetadata(this.relationshipOptions.metadataField, { value: this.relatedItem.uuid });
if (hasValue(relationMD)) {
const metadataRepresentationMD: MetadataValue = this.submissionItem.firstMetadata(this.metadataFields, { authority: relationMD.authority });
this.metadataRepresentation = Object.assign(
const nextValue = Object.assign(
new ItemMetadataRepresentation(metadataRepresentationMD),
this.relatedItem
)
);
if (hasValue(this.metadataRepresentation$)) {
this.metadataRepresentation$.next(nextValue);
} else {
this.metadataRepresentation$ = new BehaviorSubject<MetadataRepresentation>(nextValue);
}
}
}));
}

View File

@@ -35,8 +35,8 @@
[model]="_model"
[templates]="templates"
[ngClass]="[getClass('element', 'host', _model), getClass('grid', 'host', _model)]"
(dfBlur)="updateReorderables()"
(dfChange)="updateReorderables()"
(dfBlur)="update(idx)"
(dfChange)="update(idx)"
(dfFocus)="onFocus($event)"
(ngbEvent)="onCustomEvent($event, null, true)"></ds-dynamic-form-control-container>
</ng-template>

View File

@@ -1,5 +1,9 @@
@import './../../../../../../../styles/variables';
:host {
display: block;
}
.cdk-drag {
margin-left: -(2 * $spacer);
margin-right: -(0.5 * $spacer);

View File

@@ -9,7 +9,7 @@ import {
Output,
QueryList
} from '@angular/core';
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import {
DynamicFormArrayComponent,
DynamicFormArrayGroupModel,
@@ -22,7 +22,7 @@ import {
DynamicTemplateDirective
} from '@ng-dynamic-forms/core';
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { map, switchMap, take } from 'rxjs/operators';
import { RelationshipService } from '../../../../../../core/data/relationship.service';
import { RemoteData } from '../../../../../../core/data/remote-data';
import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model';
@@ -34,7 +34,7 @@ import {
} from '../../../../../../core/shared/operators';
import { SubmissionObject } from '../../../../../../core/submission/models/submission-object.model';
import { SubmissionObjectDataService } from '../../../../../../core/submission/submission-object-data.service';
import { hasNoValue, hasValue, isEmpty, isNotEmpty, isNull } from '../../../../../empty.util';
import { hasValue } from '../../../../../empty.util';
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
import {
Reorderable,
@@ -43,11 +43,7 @@ import {
} from '../../existing-metadata-list-element/existing-metadata-list-element.component';
import { DynamicConcatModel } from '../ds-dynamic-concat.model';
import { DynamicRowArrayModel } from '../ds-dynamic-row-array-model';
import { SaveSubmissionSectionFormSuccessAction } from '../../../../../../submission/objects/submission-objects.actions';
import { Store } from '@ngrx/store';
import { SubmissionState } from '../../../../../../submission/submission.reducers';
import { ObjectCacheService } from '../../../../../../core/cache/object-cache.service';
import { RequestService } from '../../../../../../core/data/request.service';
import { SubmissionService } from '../../../../../../submission/submission.service';
import { AppState } from '../../../../../../app.reducer';
import { followLink } from '../../../../../utils/follow-link-config.model';
@@ -115,7 +111,10 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent imple
.filter(([group, control], index) => index > 0 && hasValue((group.group[0] as any).value)) // disregard the first group, it is always empty to ensure the first field remains empty
.map(([group, control]: [DynamicFormArrayGroupModel, AbstractControl], index: number) => {
const model = group.group[0] as DynamicConcatModel;
// console.log('model.id', model.id);
// console.log('model.value', model.value);
let formFieldMetadataValue: FormFieldMetadataValueObject = model.value as FormFieldMetadataValueObject;
// console.log('formFieldMetadataValue', formFieldMetadataValue);
if (hasValue(formFieldMetadataValue)) {
const metadataValue = Object.assign(new MetadataValue(), {
value: formFieldMetadataValue.display,
@@ -192,13 +191,14 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent imple
hasMetadataField = true;
updatedReorderable.subscribe((v) => {
const reoMD = reorderable as ReorderableFormFieldMetadataValue;
const mdl = Object.assign({}, reoMD.model, { value: reoMD.metadataValue });
reoMD.model.value = reoMD.metadataValue;
console.log('reoMD', reoMD);
this.onChange({
$event: { previousIndex: prevIndex },
context: { index },
control: reoMD.control,
group: this.group,
model: mdl,
model: reoMD.model,
type: DynamicFormControlEventType.Change
});
});
@@ -225,4 +225,10 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent imple
this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex);
this.updateReorderables();
}
update(index: number) {
if (index > 0) {
this.updateReorderables();
}
}
}

View File

@@ -14,6 +14,7 @@ export const CONCAT_SECOND_INPUT_SUFFIX = '_CONCAT_SECOND_INPUT';
export interface DynamicConcatModelConfig extends DynamicFormGroupModelConfig {
separator: string;
value?: any;
hint?: string;
relationship?: RelationshipOptions;
repeatable: boolean;
required: boolean;
@@ -28,6 +29,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel {
@serializable() relationship?: RelationshipOptions;
@serializable() repeatable?: boolean;
@serializable() required?: boolean;
@serializable() hint?: string;
@serializable() metadataFields: string[];
@serializable() submissionId: string;
@@ -41,6 +43,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel {
this.relationship = config.relationship;
this.repeatable = config.repeatable;
this.required = config.required;
this.hint = config.hint;
this.metadataFields = config.metadataFields;
this.submissionId = config.submissionId;
this.valueUpdates = new Subject<string>();

View File

@@ -1,8 +1,7 @@
<div #sdRef="ngbDropdown" ngbDropdown class="input-group w-100">
<input class="form-control"
<input #inputElement class="form-control"
[attr.autoComplete]="model.autoComplete"
[class.is-invalid]="showErrorMessages"
[dynamicId]="bindId && model.id"
[name]="model.name"
[readonly]="model.readOnly"
[type]="model.inputType"
@@ -11,9 +10,8 @@
(click)="$event.stopPropagation(); openDropdown(sdRef);"
(focus)="onFocus($event)"
(keypress)="$event.preventDefault()">
<button aria-describedby="collectionControlsMenuLabel"
<button #buttonElement aria-describedby="collectionControlsMenuLabel"
class="ds-form-input-btn btn btn-outline-primary"
id="scrollableDropdownMenuButton_{{model.id}}"
ngbDropdownToggle
[disabled]="model.readOnly"
(click)="onToggle(sdRef); $event.stopPropagation();"></button>

View File

@@ -48,6 +48,7 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp
}
ngOnInit() {
// console.log('ngOnInit', this.model, this.model.value);
this.searchOptions = new IntegrationSearchOptions(
this.model.authorityOptions.scope,
this.model.authorityOptions.name,
@@ -65,6 +66,7 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp
}),
first())
.subscribe((object: IntegrationData) => {
// console.log('ngOnInit subscribe', object, this.model, this.model.value);
this.optionsList = object.payload;
if (this.model.value) {
this.setCurrentValue(this.model.value);

View File

@@ -163,13 +163,10 @@ export class RelationshipEffects {
this.relationshipService.getRelationshipByItemsAndLabel(item1, item2, relationshipType).pipe(
take(1),
hasValueOperator(),
tap((v) => console.log('before delete', v)),
mergeMap((relationship: Relationship) => this.relationshipService.deleteRelationship(relationship.id, 'none')),
take(1),
tap((v) => console.log('before refresh', v)),
switchMap(() => this.refreshWorkspaceItemInCache(submissionId)),
).subscribe((submissionObject: SubmissionObject) => {
console.log('in subscribe', submissionObject);
this.store.dispatch(new SaveSubmissionSectionFormSuccessAction(submissionId, [submissionObject], false))
});
}