Skip to content

Commit

Permalink
fix: language input bug for list item (#1405)
Browse files Browse the repository at this point in the history
Co-authored-by: Irmantas Kaukas <irmastnt@gmail.com>
  • Loading branch information
derschnee68 and irmastnt committed Jan 30, 2024
1 parent 07a9686 commit 79f6bd8
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 66 deletions.
Expand Up @@ -17,7 +17,8 @@ import { ListItemService } from '../list-item/list-item.service';
[placeholder]="node.labels | appStringifyStringLiteral: 'all' | appTruncate: 128"
[editable]="false"
[formGroup]="readOnlyForm"
controlName="labels">
controlName="labels"
[validators]="[]">
</dasch-swiss-multi-language-input>
<app-action-bubble
Expand Down
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ListInfoResponse, ListNode, ListNodeInfoResponse } from '@dasch-swiss/dsp-js';
import { ListApiService } from '@dasch-swiss/vre/shared/app-api';
import { ProjectService } from '@dasch-swiss/vre/shared/app-helper-services';
Expand All @@ -20,7 +20,8 @@ export class ListNodeOperation {
style="flex: 1"
[formGroup]="form"
controlName="labels"
[placeholder]="placeholder">
[placeholder]="placeholder"
[validators]="labelsValidators">
</dasch-swiss-multi-language-input>
<button color="primary" mat-icon-button matSuffix [disabled]="form.invalid" type="submit">
<mat-icon> add</mat-icon>
Expand All @@ -33,8 +34,7 @@ export class ListItemFormComponent implements OnInit {
placeholder: string;
form: FormGroup;

readonly FORM_DEFAULT_VALUE = [{ language: 'de', value: '' }];

readonly labelsValidators = [Validators.maxLength(2000)];
constructor(
private _listApiService: ListApiService,
private _fb: FormBuilder,
Expand Down Expand Up @@ -79,19 +79,11 @@ export class ListItemFormComponent implements OnInit {

private _buildForm() {
this.form = this._fb.group({
labels: this._fb.array(
this.FORM_DEFAULT_VALUE.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.maxLength(2000)]],
})
),
atLeastOneStringRequired('value')
),
labels: this._fb.array([], atLeastOneStringRequired('value')),
});
}

private _resetForm() {
this.form.reset({ labels: this.FORM_DEFAULT_VALUE });
(this.form.get('labels') as FormArray).clear();
}
}
Expand Up @@ -8,10 +8,18 @@ import { atLeastOneStringRequired } from '../../../main/form-validators/at-least
@Component({
selector: 'app-reusable-list-item-form',
template: `
<dasch-swiss-multi-language-input placeholder="Child node label *" [formGroup]="form" controlName="labels">
<dasch-swiss-multi-language-input
placeholder="Child node label *"
[formGroup]="form"
controlName="labels"
[validators]="labelsValidators">
</dasch-swiss-multi-language-input>
<dasch-swiss-multi-language-textarea placeholder="Child node description" [formGroup]="form" controlName="comments">
<dasch-swiss-multi-language-textarea
placeholder="Child node description"
[formGroup]="form"
controlName="comments"
[validators]="commentsValidators">
</dasch-swiss-multi-language-textarea>
`,
})
Expand All @@ -26,6 +34,9 @@ export class ReusableListItemFormComponent implements OnInit, OnDestroy {
form: FormGroup;
subscription: Subscription;

readonly labelsValidators = [Validators.required, Validators.maxLength(2000)];
readonly commentsValidators = [Validators.required, Validators.maxLength(2000)];

constructor(private _fb: FormBuilder) {}

ngOnInit() {
Expand All @@ -46,7 +57,7 @@ export class ReusableListItemFormComponent implements OnInit, OnDestroy {
this.formData.labels.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.required, Validators.maxLength(2000)]],
value: [value, this.labelsValidators],
})
),
atLeastOneStringRequired('value')
Expand All @@ -55,7 +66,7 @@ export class ReusableListItemFormComponent implements OnInit, OnDestroy {
this.formData.comments.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.required, Validators.maxLength(2000)]],
value: [value, this.commentsValidators],
})
)
),
Expand Down
Expand Up @@ -21,14 +21,19 @@ import { CustomRegex } from '../../../workspace/resource/values/custom-regex';
placeholder="Class name *"
prefixIcon="fingerprint"></app-common-input>
<dasch-swiss-multi-language-input placeholder="Label *" [formGroup]="form" controlName="labels">
<dasch-swiss-multi-language-input
placeholder="Label *"
[formGroup]="form"
controlName="labels"
[validators]="labelsValidators">
</dasch-swiss-multi-language-input>
<dasch-swiss-multi-language-textarea
placeholder="Comment *"
[formGroup]="form"
controlName="comments"
[editable]="true">
[editable]="true"
[validators]="commentsValidators">
</dasch-swiss-multi-language-textarea>
</form>
`,
Expand All @@ -46,6 +51,8 @@ export class ResourceClassFormComponent implements OnInit, OnDestroy {
existingNames: [RegExp] = [new RegExp('anEmptyRegularExpressionWasntPossible')];
ontology;
subscription: Subscription;
readonly labelsValidators = [Validators.maxLength(2000)];
readonly commentsValidators = [Validators.maxLength(2000)];

constructor(
private _fb: FormBuilder,
Expand Down Expand Up @@ -92,7 +99,7 @@ export class ResourceClassFormComponent implements OnInit, OnDestroy {
this.formData.labels.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.maxLength(2000)]],
value: [value, this.labelsValidators],
})
),
atLeastOneStringRequired('value')
Expand All @@ -101,7 +108,7 @@ export class ResourceClassFormComponent implements OnInit, OnDestroy {
this.formData.comments.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.maxLength(2000)]],
value: [value, this.commentsValidators],
})
),
atLeastOneStringRequired('value')
Expand Down
Expand Up @@ -36,7 +36,8 @@ import { shortcodeExistsValidator } from './shortcode-exists.validator';
<dasch-swiss-multi-language-textarea
[placeholder]="('appLabels.form.project.general.description' | translate) + '*'"
[formGroup]="form"
controlName="description">
controlName="description"
[validators]="descriptionValidators">
</dasch-swiss-multi-language-textarea>
<app-chip-list-input
Expand All @@ -60,6 +61,7 @@ export class ReusableProjectFormComponent implements OnInit, OnDestroy {
shortcodePatternError = { errorKey: 'pattern', message: 'This field must contains letters from A to F and 0 to 9' };
shortCodeExistsError = { errorKey: 'shortcodeExists', message: 'This shortcode already exists' };
readonly keywordsValidators = [Validators.minLength(3), Validators.maxLength(64)];
readonly descriptionValidators = [Validators.maxLength(2000)];
subscription: Subscription;

constructor(
Expand Down Expand Up @@ -98,7 +100,7 @@ export class ReusableProjectFormComponent implements OnInit, OnDestroy {
this.formData.description.map(({ language, value }) =>
this._fb.group({
language,
value: [value, [Validators.maxLength(2000)]],
value: [value, this.descriptionValidators],
})
),
atLeastOneStringRequired('value')
Expand Down
@@ -1,5 +1,5 @@
import { ElementRef, Injectable } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { ChangeDetectorRef, ElementRef, Injectable } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms';
import { UserSelectors } from '@dasch-swiss/vre/shared/app-state';
import { Store } from '@ngxs/store';

Expand All @@ -9,16 +9,19 @@ import { Store } from '@ngxs/store';
*/
@Injectable()
export class MultiLanguageFormService {
readonly availableLanguages: string[] = ['de', 'fr', 'it', 'en', 'rm'];
readonly availableLanguages = ['de', 'fr', 'it', 'en', 'rm'];
selectedLanguageIndex: number;
formGroup: FormGroup;
controlName: string;
validators: ValidatorFn[];

inputValue: string | null = null;

get formArray() {
return this.formGroup.controls[this.controlName] as FormArray;
}

get selectedFormControl() {
get selectedFormControl(): FormControl {
return (
this.formArray.controls.find(
control => control.value.language === this.availableLanguages[this.selectedLanguageIndex]
Expand All @@ -40,40 +43,58 @@ export class MultiLanguageFormService {

constructor(
private _store: Store,
private _fb: FormBuilder
private _fb: FormBuilder,
private _cd: ChangeDetectorRef
) {}

onInit(formGroup: FormGroup, controlName: string) {
onInit(formGroup: FormGroup, controlName: string, validators: ValidatorFn[]) {
this.formGroup = formGroup;
this.controlName = controlName;
this.selectedLanguageIndex = this._setupLanguageIndex();
}
this.validators = validators;

getFormControlWithLanguage(lang: string) {
return this.formArray.controls.find(control => control.value.language === lang && control.value.value !== '');
this.formArray.valueChanges.subscribe(array => {
if (array.length === 0) {
this.inputValue = null;
this._cd.detectChanges(); // TODO remove later
}
});
}

changeLanguage(languageIndex: number, deleteCurrentIfEmpty = true) {
const currentValidators = (this.formArray.controls[0].get('value') as FormControl).validator;

if (deleteCurrentIfEmpty && this.selectedFormControl.value.length === 0) {
this.formArray.removeAt(this.formArray.controls.indexOf(this.selectedFormControl));
onInputChange(newText: any) {
if (newText === '') {
if (this.inputValue && this.inputValue.length > 0) {
this.formArray.removeAt(this.formArray.controls.indexOf(this.selectedFormControl));
this.inputValue = null;
}
return;
}

const language = this.availableLanguages[languageIndex];
const languageFoundIndex = this.formArray.value.findIndex(array => array.language === language);

if (languageFoundIndex === -1) {
if (this.inputValue === null) {
this.formArray.push(
this._fb.group({
language,
value: ['', currentValidators],
language: this.availableLanguages[this.selectedLanguageIndex],
value: [newText, this.validators],
})
);
this.changeLanguage(languageIndex, false);
} else {
this.selectedLanguageIndex = languageIndex;
}

this.selectedFormControl.setValue(newText);
this.inputValue = newText;
}

getFormControlWithLanguage(lang: string) {
return this.formArray.controls.find(control => control.value.language === lang && control.value.value !== '');
}

changeLanguage(languageIndex: number) {
this.selectedLanguageIndex = languageIndex;

const newFormControl = this.formArray.controls.find(
control => control.value.language === this.availableLanguages[this.selectedLanguageIndex]
);

this.inputValue = newFormControl ? this.selectedFormControl.value : null;
}

private _setupLanguageIndex(): number {
Expand All @@ -90,11 +111,9 @@ export class MultiLanguageFormService {

// with user favorite language
if (indexFavoriteLanguage !== -1) {
this._addEmptyFormControl(userFavoriteLanguage);
return indexFavoriteLanguage;
// with default language
} else {
this._addEmptyFormControl(this.availableLanguages[0]);
return 0;
}
}
Expand All @@ -105,13 +124,4 @@ export class MultiLanguageFormService {

return this.availableLanguages.indexOf(responseLanguages[0]);
}

private _addEmptyFormControl(language: string) {
this.formArray.push(
this._fb.group({
language,
value: '',
})
);
}
}
@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormGroup, FormsModule, ReactiveFormsModule, ValidatorFn } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatIconModule } from '@angular/material/icon';
Expand Down Expand Up @@ -48,8 +48,9 @@ import { MultiLanguageFormService } from './multi-language-form.service';
<input
matInput
[placeholder]="placeholder"
[formControl]="formService.selectedFormControl"
#textInput
[ngModel]="formService.inputValue"
(ngModelChange)="formService.onInputChange($event)"
[readonly]="!editable" />
</mat-form-field>
<mat-error *ngIf="formService.formArray.invalid && formService.formArray.touched">
Expand Down Expand Up @@ -89,10 +90,11 @@ export class MutiLanguageInputComponent implements OnInit {
@Input() controlName: string;
@Input() editable = true;
@Input() placeholder: string;
@Input() validators: ValidatorFn[];

constructor(public formService: MultiLanguageFormService) {}

ngOnInit() {
this.formService.onInit(this.formGroup, this.controlName);
this.formService.onInit(this.formGroup, this.controlName, this.validators);
}
}
@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormGroup, FormsModule, ReactiveFormsModule, ValidatorFn } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatIconModule } from '@angular/material/icon';
Expand Down Expand Up @@ -44,8 +44,8 @@ import { MultiLanguageFormService } from './multi-language-form.service';
[placeholder]="placeholder"
#textInput
[readonly]="!editable"
[formControl]="formService.selectedFormControl">
</textarea>
[ngModel]="formService.inputValue"
(ngModelChange)="formService.onInputChange($event)"></textarea>
</mat-form-field>
</div>
<mat-error *ngIf="formService.formArray.invalid && formService.formArray.touched">
Expand Down Expand Up @@ -76,10 +76,11 @@ export class MultiLanguageTextareaComponent implements OnInit {
@Input() controlName: string;
@Input() editable = true;
@Input() placeholder: string;
@Input() validators: ValidatorFn[];

constructor(public formService: MultiLanguageFormService) {}

ngOnInit() {
this.formService.onInit(this.formGroup, this.controlName);
this.formService.onInit(this.formGroup, this.controlName, this.validators);
}
}

0 comments on commit 79f6bd8

Please sign in to comment.