added custom extra propertiex

This commit is contained in:
Maria Teresa Paratore 2024-04-04 15:30:11 +02:00
parent 441e1a7530
commit 897f5ee1bf
22 changed files with 71 additions and 544 deletions

View File

@ -1,3 +0,0 @@
<h2>Modular Form: </h2>
<jhi-dynamic-form [questions]="questions$ | async"></jhi-dynamic-form>
<button routerLink="/">Back</button>

View File

@ -1,41 +0,0 @@
/* eslint-disable @angular-eslint/no-empty-lifecycle-method */
/* eslint-disable @typescript-eslint/no-empty-function */
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { ReactiveFormsModule,Validators } from '@angular/forms';
import { Router, RouterModule } from '@angular/router';
import { DynamicFormComponent } from 'app/dynamic-form/dynamic-form.component';
import { DynamicFormQuestionComponent } from 'app/dynamic-form/dynamic-form-question.component';
import { QuestionService } from 'app/dynamic-form/question.service';
import { Observable } from 'rxjs';
import { QuestionBase } from 'app/dynamic-form/question-base';
import { MatDialogModule } from '@angular/material/dialog';
@Component({
standalone:true,
selector: 'jhi-add-resource',
templateUrl: './add-resource.component.html',
styleUrls: ['./add-resource.component.scss'],
providers: [QuestionService],
imports:[CommonModule,DynamicFormComponent,DynamicFormQuestionComponent,
ReactiveFormsModule,RouterModule,
MatDialogModule]
})
export class AddResourceComponent implements OnInit {
//PER FORM DINAMICA
questions$: Observable<QuestionBase<any>[]>;
constructor(private router:Router, private formService: QuestionService) {
this.questions$ = formService.getQuestions('HostingNode');
}
ngOnInit(): void {
}
}

View File

@ -1,13 +0,0 @@
import { Routes } from '@angular/router';
import { AddResourceComponent } from './add-resource.component';
export const addResourceRoutes: Routes = [
{
path: '',
component: AddResourceComponent,
data: {
pageTitle: 'Test Modular Form',
},
},
];

View File

@ -1,16 +0,0 @@
<div [formGroup]="form">
<label [attr.for]="question.key">{{question.label}}</label>
<div [ngSwitch]="question.controlType">
<input *ngSwitchCase="'textbox'" [formControlName]="question.key"
[id]="question.key" [type]="question.type"/>
<select *ngSwitchCase="'dropdown'" [formControlName]="question.key" [id]="question.key" >
<option *ngFor="let opt of question.options" [value]="opt.key">{{opt.value}}</option>
</select>
</div>
<div class="errorMessage" *ngIf="!isValid">{{question.label}} is required</div>
</div>

View File

@ -1,26 +0,0 @@
/* eslint-disable @typescript-eslint/member-ordering */
/* eslint-disable @angular-eslint/no-empty-lifecycle-method */
/* eslint-disable @typescript-eslint/no-empty-function */
import { Component, Input } from '@angular/core';
import { QuestionBase } from './question-base';
import { FormGroup, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { MaterialModule } from 'app/shared/material/material.module';
@Component({
standalone:true,
selector: 'jhi-dynamic-form-question',
templateUrl: './dynamic-form-question.component.html',
styleUrls: ['./dynamic-form-question.component.scss'],
imports:[CommonModule, ReactiveFormsModule,MaterialModule]
})
export class DynamicFormQuestionComponent {
@Input() question!: QuestionBase<string>;
@Input() form!: FormGroup;
get isValid():boolean {
return this.form.controls[this.question.key].valid;
}
}

View File

@ -1,49 +0,0 @@
<mat-expansion-panel hideToggle>
<mat-expansion-panel-header>
<mat-panel-title>
NetworkingFacet (isIdentifiedBy)
</mat-panel-title>
<mat-panel-description>
Description: The network ID characterizing the Hosting Node.
</mat-panel-description>
</mat-expansion-panel-header>
<p>
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let question of questions" class="form-row">
<jhi-dynamic-form-question [question]="question" [form]="form"></jhi-dynamic-form-question>
</div>
<button mat-button type="submit" [disabled]="!form.valid">Save</button>
</form>
<div *ngIf="payLoad" class="form-row">
<strong>Saved the following values</strong><br>{{payLoad}}
</div>
</mat-expansion-panel>
<mat-expansion-panel hideToggle>
<mat-expansion-panel-header>
<mat-panel-title>
CPUFacet (consistsOf)
</mat-panel-title>
<mat-panel-description>
Description: The CPU equipping the Hosting Node.
</mat-panel-description>
</mat-expansion-panel-header>
<p>
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let question of questions" class="form-row">
<jhi-dynamic-form-question [question]="question" [form]="form"></jhi-dynamic-form-question>
</div>
<button mat-button type="submit" [disabled]="!form.valid">Save</button>
</form>
<div *ngIf="payLoad" class="form-row">
<strong>Saved the following values</strong><br>{{payLoad}}
</div>
</mat-expansion-panel>

View File

@ -1,41 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @angular-eslint/no-empty-lifecycle-method */
/* eslint-disable @typescript-eslint/no-empty-function */
import { Component, OnInit, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { QuestionControlService } from './question-control.service';
import { DynamicFormQuestionComponent } from './dynamic-form-question.component';
import { FormGroup, ReactiveFormsModule } from '@angular/forms';
import { QuestionBase } from './question-base';
/*
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
*/
import { MaterialModule } from 'app/shared/material/material.module';
@Component({
standalone:true,
selector: 'jhi-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.scss'],
providers: [QuestionControlService],
imports:[CommonModule,DynamicFormQuestionComponent,ReactiveFormsModule,MaterialModule]
})
export class DynamicFormComponent implements OnInit {
@Input() questions: QuestionBase<string>[] | null = [];
form!: FormGroup;
payLoad = '';
constructor(private qcs: QuestionControlService) {}
ngOnInit() {
this.form = this.qcs.toFormGroup(this.questions as QuestionBase<string>[]);
}
onSubmit() {
this.payLoad = JSON.stringify(this.form.getRawValue());
}
}

View File

@ -1,38 +0,0 @@
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
export class QuestionBase<T> {
value: T|undefined;
key: string;
label: string;
required: boolean;
// order: number;
controlType: string;
type: string;
options: {key: string, value: string}[];
title: string;
description:string;
constructor(options: {
value?: T;
key?: string;
label?: string;
required?: boolean;
// order?: number;
controlType?: string;
type?: string;
options?: {key: string, value: string}[];
title?: string;
description?: string;
} = {}) {
this.value = options.value;
this.key = options.key || '';
this.label = options.label || '';
this.required = !!options.required;
// this.order = options.order === undefined ? 1 : options.order;
this.controlType = options.controlType || '';
this.type = options.type || '';
this.options = options.options || [];
this.title = options.title || '';
this.description = options.description || '';
}
}

View File

@ -1,25 +0,0 @@
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable @typescript-eslint/no-empty-function */
import { Injectable } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { QuestionBase } from './question-base';
@Injectable({
providedIn: 'root'
})
@Injectable()
export class QuestionControlService {
constructor() { }
toFormGroup(questions: QuestionBase<string>[] ): FormGroup {
const group: any = {};
questions.forEach(question => {
group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
: new FormControl(question.value || '');
});
return new FormGroup(group);
}
}

View File

@ -1,5 +0,0 @@
import { QuestionBase } from './question-base';
export class DropdownQuestion extends QuestionBase<string> {
override controlType = 'dropdown';
}

View File

@ -1,5 +0,0 @@
import { QuestionBase } from './question-base';
export class TextboxQuestion extends QuestionBase<string> {
override controlType = 'textbox';
}

View File

@ -1,60 +0,0 @@
import { Injectable } from '@angular/core';
import { QuestionBase } from './question-base';
import { TextboxQuestion } from './question-textbox';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class QuestionService {
getQuestions(resourceType:string):any {
// HOSTINGNODE
const questions: QuestionBase<string>[] = [
new TextboxQuestion({
key: 'model',
label: 'CPU Model',
value: '',
required: true,
//order: 1 ,
//validate not null
}),
new TextboxQuestion({
key: 'domainName',
label: 'domain name',
// order: 2
}),
new TextboxQuestion({
key: 'Port',
label: 'Port',
type: 'number', //'text', 'email', 'password', 'number', 'date', etc., which corresponds to the types of HTML input elements.
// order: 3
}),
new TextboxQuestion({
key: 'IPAddress',
label: 'IP Address',
// order: 4
}),
new TextboxQuestion({
key: 'mask',
label: 'mask',
// order: 5
}),
new TextboxQuestion({
key: 'broadcastAddress',
label: 'broadcast address',
// order: 6
}),
];
//questo è un observable
return questions;
}
}

View File

@ -34,7 +34,7 @@
<textarea matInput formControlName="facetDescription" [readonly]="true">{{facetTemplate.value.description}}</textarea>
</div>
<mat-form-field>
<mat-label for="relationFacet" >relationFacet</mat-label>
<mat-label for="relationFacet" >relation</mat-label>
<mat-select formControlName="relationFacet" id="relationFacet">
<mat-option *ngFor="let opt of facetTemplate.value.relationOptions" [value]="opt">
{{opt}}
@ -51,23 +51,28 @@
</mat-form-field>
</div>
<!-- ADDITIONAL PROPERTIES -->
<!--
<div formArrayName="extrapropsArray" style="border: 3px solid rgb(202, 198, 57); padding: 10px; margin: 5px;">
<div [formGroupName] ="i" *ngFor="let extraCtrl of myForm.get([facetTemplate.key,ind,'additionalProps']).controls; let i=index;">
<!--TODO: AGGIUSTA QUESTO -->
<div formArrayName ="extraProps" style="border: 3px solid rgb(202, 198, 57); padding: 10px; margin: 5px;">
<div [formGroupName] ="i" *ngFor="let x of getExtraPropsArray(facetTemplate.key,ind).controls; let i=index;">
<mat-form-field>
<mat-label for="deno">name</mat-label>
<input matInput formControlName="deno" type="text"/>
</mat-form-field>
<br/>
<mat-form-field>
<mat-label for="tipo">type</mat-label>
<input matInput formControlName="tipo" type="text"/>
</mat-form-field>
<button mat-flat-button color="accent"
(click)="addFacet(facetTemplate.key)" >
Remove custom prop</button>
(click)="removeExtraProp(facetTemplate.key,ind,i)" >
Remove custom property</button>
</div>
</div>
<button mat-flat-button color="accent"
(click)="addFacet(facetTemplate.key)" >
Add new custom prop</button>
</div>
-->
(click)="addExtraProp(facetTemplate.key,ind)" >
Add custom property</button>
<!--</div> -->
<!-- FINE ADDITIONAL PROPERTIES -->
<input matInput formControlName="isAdded" style="display: none;"/>

View File

@ -80,25 +80,64 @@ export class FacetComposerComponent implements OnInit {
const nameplus:string = item.name+'_'+item.relation;
const singleFacetArray: FormArray = this.fb.array([]);
singleFacetArray.push(this.createFacetGroup(item,false));
//singleFacetArray.push(this.createExtraPropGroup());
this.myForm.addControl(nameplus,singleFacetArray);
}
get extraProps():FormArray {
return this.fb.array([
this.extraProp
])
}
get extraProp():FormGroup{
return this.fb.group({
deno: ['',null],
tipo: ['',Validators.required]
})
}
getExtraPropsArray(denoFacet:string, index:number):FormArray{
return (this.getSingleFacetArray(denoFacet).controls[index]).get('extraProps') as FormArray;
}
addExtraProp(denoFacet:string, index:number):void{
this.getExtraPropsArray(denoFacet, index).push(this.extraProp);
}
removeExtraProp(denoFacet:string, indexFct:number, index:number):void{
this.getExtraPropsArray(denoFacet, indexFct).removeAt(index);
}
/*
removeExtraProp(facetDeno:string, index:number) {
const singleFacetArray = this.myForm.controls[facetDeno] as FormArray;
(singleFacetArray.get("extraProps") as FormArray).removeAt(index);
// this.typeSpec.facetSpecs.splice(index,1);
}
*/
/*
addExtraProp(facetDeno:string) {
console.debug('----------------');
const bla = (this.getSingleFacetArray('CPUFacet_ConsistsOf').controls[0]).get('extraProps') as FormArray;
console.debug(bla.controls[0].get('tipo')?.value);
console.debug('----------------');
}
*/
addFacet(deno:string): void {
const icf: IFacetComposer = <IFacetComposer>this.fieldsMap.get(deno);
const singleFacetArray = this.myForm.controls[deno] as FormArray;
singleFacetArray.push(this.createFacetGroup(icf,true));
//singleFacetArray.push(this.createExtraPropGroup());
}
createExtraPropGroup(): FormGroup{
const extraFg: FormGroup = this.fb.group({});
extraFg.addControl('deno', '');
return extraFg;
}
createFacetGroup(item: IFacetComposer,isAdded: boolean):FormGroup{
const facetFg: FormGroup = this.fb.group({});
const nameFc = this.fb.control(item.name);
@ -119,7 +158,9 @@ export class FacetComposerComponent implements OnInit {
const addedFc = this.fb.control(isAdded);
facetFg.addControl('isAdded', addedFc);
facetFg.addControl('extraProps', this.extraProps);
//1. creo group con le properties
//2. aggiungo formgroup delle properties ai controls per la facet
// facetFg.addControl('properties',this.createPropertyControls(item.guiProps));
@ -156,17 +197,13 @@ export class FacetComposerComponent implements OnInit {
}
facetFg.addControl(prop.name,fc); //formGroup.addControl('controlName', formControl);
}
console.debug("----------- facetFg -------");
console.debug(facetFg)
console.debug("-----------------");
/*
console.debug("------------------");
console.debug(facetFg);
console.debug("------------------");
*/
return facetFg;
}
/*
getExtraPropsArray(nameplus:string): FormArray {
const fa = this.getSingleFacetArray(nameplus);
return fa.controls['extraPropsArray'] as FormArray
}*/
getSingleFacetArray(nameplus:string): FormArray {
return this.myForm.controls[nameplus] as FormArray;

View File

@ -1,44 +0,0 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DummyService {
constructor() {}
// eslint-disable-next-line @typescript-eslint/member-ordering
todoList = [
{
title: 'delectus aut autem',
completed: false,
priority: 0,
},
{
title: 'quis ut nam facilis et officia qui',
completed: false,
priority: 1,
},
{
title: 'fugiat veniam minus',
completed: false,
priority: 2,
},
{
title: 'et porro tempora',
completed: true,
priority: 1,
},
{
title: 'laboriosam mollitia et enim quasi adipisci quia provident illum',
completed: false,
priority: 0,
},
];
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
getMyData() {
return [...this.todoList];
}
}

View File

@ -1,17 +0,0 @@
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
export class Facet<T> {
value: T|undefined;
key: string;
properties: {key: string, value: string}[];
constructor(options: {
value?: T;
key?: string;
label?: string;
properties?: {key: string, value: string}[];
} = {}) {
this.value = options.value;
this.key = options.key || '';
this.properties = options.properties || [];
}
}

View File

@ -1,50 +0,0 @@
<form class="form-group" [formGroup]="toDoListForm">
<div formArrayName="items">
<table class="table-bordered" *ngIf="itemsArray.value.length">
<tr>
<th>ItemName</th>
<th>Completed</th>
<th>Priority</th>
<th>Action</th>
</tr>
<tr
*ngFor="let x of itemsArray.controls; let i = index; ngForTrackBy: track"
[formGroupName]="i"
>
<td>
<input
class="form-control"
formControlName="title"
placeholder="Item name"
/>
</td>
<td>
<input
class="form-control"
type="checkbox"
formControlName="completed"
/>
</td>
<td>
<select class="form-control" formControlName="priority">
<option disabled selected hidden value="null">
Select Priority
</option>
<option *ngFor="let m of prio" [value]="m">{{ m }}</option>
</select>
</td>
<td>
<button (click)="deleteItem(i)">Delete Item</button>
</td>
</tr>
</table>
</div>
<button (click)="addNewItem()" enab>Add New Item</button>
<button (click)="deleteAll()">Delete All</button>
</form>
<b>Form's Value:</b>
{{ toDoListForm.value | json }}
<br />
<b>Form is Valid ? :</b>
{{ toDoListForm.valid }}

View File

@ -1,82 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/member-ordering */
/* eslint-disable no-console */
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormArray, FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { DummyService } from './dummy.service';
export interface Item {
title: string;
completed: boolean;
priority: number;
}
@Component({
standalone: true,
selector: 'jhi-form-composer',
templateUrl: './form-composer.component.html',
styleUrls: ['./form-composer.component.scss'],
imports:[CommonModule, ReactiveFormsModule, RouterModule]
})
export class FormComposerComponent implements OnInit{
constructor(private serv: DummyService, private fb: FormBuilder) {}
prio = [0, 1, 2];
toDoListForm: FormGroup | any;
itemsList: Item[] = [];
defaultItem = {
title: '',
completed: false,
priority: null,
};
get itemsArray() {
return <FormArray>this.toDoListForm.get('items');
}
ngOnInit(): void {
this.toDoListForm = this.fb.group({
items: this.fb.array([]), //array di formControls
});
this.itemsList = this.serv.getMyData();
this.displayItems();
}
createItem(item: any) {
return this.fb.group({
title: [item.title, [Validators.required]],
completed: [item.completed, [Validators.required]],
priority: [item.priority, [Validators.required]],
});
}
addNewItem() {
const formGroup = this.createItem(this.defaultItem);
this.itemsArray.push(formGroup);
}
displayItems() {
const transformedItems = this.itemsList.map((item: any) =>
this.createItem(item) // per ogni item JSON costruisce un FormGroup
);
console.log(transformedItems);
this.toDoListForm.setControl('items', this.fb.array(transformedItems)) //assegno un formArray di FormGroup;
}
deleteItem(i: number) {
this.itemsArray.removeAt(i);
}
deleteAll() {
this.itemsArray.clear();
}
/*
track(item: any, index: number) {
return index;
}
*/
}