Solved problems with autocomplete and form validation (reactive forms)
This commit is contained in:
parent
970b8b87d2
commit
7f4458cdc3
|
@ -1,5 +1,5 @@
|
||||||
<div class="d-flex flex-row py-4">
|
<div class="d-flex flex-row py-4">
|
||||||
<div id="btn-group" class="col-md-3 mt-2">
|
<div id="btn-group" class="col-md-3 mt-3">
|
||||||
<button mat-raised-button color="primary"><mat-icon>source</mat-icon> <span>File</span></button>
|
<button mat-raised-button color="primary"><mat-icon>source</mat-icon> <span>File</span></button>
|
||||||
<button mat-raised-button color="primary"><mat-icon>edit</mat-icon> <span>Edit</span></button>
|
<button mat-raised-button color="primary"><mat-icon>edit</mat-icon> <span>Edit</span></button>
|
||||||
<button mat-raised-button color="primary"><mat-icon>explore</mat-icon> <span>View</span></button>
|
<button mat-raised-button color="primary"><mat-icon>explore</mat-icon> <span>View</span></button>
|
||||||
|
@ -9,17 +9,8 @@
|
||||||
|
|
||||||
<div class="col-md-9 mt-2">
|
<div class="col-md-9 mt-2">
|
||||||
<form [formGroup]="chooseContextForm">
|
<form [formGroup]="chooseContextForm">
|
||||||
<!--
|
|
||||||
<label for="first-name">First Name: </label>
|
|
||||||
<input id="first-name" type="text" formControlName="firstName">
|
|
||||||
|
|
||||||
<label for="last-name">Last Name: </label>
|
|
||||||
<input id="last-name" type="text" formControlName="lastName">
|
|
||||||
-->
|
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="form-field">
|
<mat-form-field appearance="outline" class="form-field">
|
||||||
<mat-label for="namefield" class="ml-4 flex-grow-1">Context name</mat-label>
|
<mat-label for="namefield" class="ml-4 flex-grow-1">Context name</mat-label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
#contextInput
|
#contextInput
|
||||||
|
@ -27,43 +18,28 @@
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
type="text"
|
type="text"
|
||||||
[formControlName]="namefield"
|
[formControl]="namefield"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<mat-error>Please enter context!</mat-error>
|
||||||
<mat-autocomplete #auto="matAutocomplete">
|
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
|
||||||
<mat-option
|
<mat-option *ngFor="let ctx of filteredContexts | async" [value]="ctx.name">
|
||||||
(onSelectionChange)="(contextInput.value != undefined)"
|
<span>{{ ctx.name }}</span>
|
||||||
*ngFor="let ctx of filteredContexts | async"
|
<small> | ID: {{ ctx.id }}</small>
|
||||||
[value]="ctx.name"
|
</mat-option>
|
||||||
>{{ ctx.name }}</mat-option
|
|
||||||
>
|
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="form-field">
|
<mat-form-field appearance="outline" class="form-field">
|
||||||
<mat-label for="uidfield">Context UUID</mat-label>
|
<mat-label for="uidfield">Context UUID</mat-label>
|
||||||
<input matInput id="uidfield" type="text" placeholder="UUID" formControlName="uidfield" readonly />
|
<input matInput id="uidfield" type="text" placeholder="UUID" formControlName="uidfield" readonly />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
<button mat-button color="primary"><mat-icon class="icon-wide2">content_copy</mat-icon></button>
|
||||||
<!--
|
|
||||||
<div class="form-group">
|
|
||||||
<mat-form-field appearance="outline" class="form-field">
|
|
||||||
<mat-label class="ml-4 flex-grow-1">UUID</mat-label>
|
|
||||||
<input type="text" [formControl]="idCtrl" >
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
</form>
|
</form>
|
||||||
<!--
|
</div>
|
||||||
<mat-form-field>
|
</div>
|
||||||
<mat-label class="ml-4 flex-grow-1">UUID</mat-label>
|
<div class="d-flex flex-row">
|
||||||
<input #uuidInput placeholder="UUID" [formControl]="contextCtrl" contenteditable="false" />
|
<div class="col-md-3">
|
||||||
</mat-form-field>
|
|
||||||
-->
|
|
||||||
<div class="row">
|
|
||||||
<h3>Resource tree</h3>
|
<h3>Resource tree</h3>
|
||||||
<div class="d-flex flex-row col-md-3">
|
|
||||||
<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="resources-tree">
|
<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="resources-tree">
|
||||||
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
|
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
|
||||||
<button mat-button (click)="treeNode.emit(node)">
|
<button mat-button (click)="treeNode.emit(node)">
|
||||||
|
@ -91,6 +67,4 @@
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<jhi-table-screen> </jhi-table-screen>
|
<jhi-table-screen> </jhi-table-screen>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -47,3 +47,7 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-wide2 {
|
||||||
|
transform: scale(2);
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ import { NestedTreeControl } from '@angular/cdk/tree';
|
||||||
import { ResourcesLoaderService } from 'app/services/resources-loader.service';
|
import { ResourcesLoaderService } from 'app/services/resources-loader.service';
|
||||||
import { IResource } from 'app/services/i-resource';
|
import { IResource } from 'app/services/i-resource';
|
||||||
import { ContextsLoaderService } from 'app/services/contexts-loader.service';
|
import { ContextsLoaderService } from 'app/services/contexts-loader.service';
|
||||||
import { IContextNode } from 'app/services/i-context-node';
|
import { ContextNode, IContextNode } from 'app/services/i-context-node';
|
||||||
import { Observable, map, startWith } from 'rxjs';
|
import { Observable, map, startWith } from 'rxjs';
|
||||||
import { FormControl, FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'jhi-rsc-tree',
|
selector: 'jhi-rsc-tree',
|
||||||
|
@ -20,57 +20,62 @@ export class RscTreeComponent implements OnInit {
|
||||||
nestedDataSource = new MatTreeNestedDataSource<IResource>();
|
nestedDataSource = new MatTreeNestedDataSource<IResource>();
|
||||||
@Output() treeNode = new EventEmitter<IResource>(); //emitting event to parent
|
@Output() treeNode = new EventEmitter<IResource>(); //emitting event to parent
|
||||||
|
|
||||||
allContexts: IContextNode[];
|
contexts: ContextNode[];
|
||||||
filteredContexts: Observable<IContextNode[]> | any;
|
filteredContexts: Observable<ContextNode[]> | any;
|
||||||
|
chooseContextForm: FormGroup | any;
|
||||||
|
|
||||||
chooseContextForm = new FormGroup({
|
constructor(private fb: FormBuilder, private resLoader: ResourcesLoaderService, private ctxLoader: ContextsLoaderService) {
|
||||||
namefield: new FormControl(''),
|
this.contexts = [];
|
||||||
uidfield: new FormControl(''),
|
|
||||||
});
|
|
||||||
|
|
||||||
constructor(private resLoader: ResourcesLoaderService, private ctxLoader: ContextsLoaderService, private formBuilder: FormBuilder) {
|
|
||||||
this.allContexts = {} as IContextNode[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//MT: per chiamare le direttive formControlName
|
|
||||||
get namefield(): any {
|
get namefield(): any {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return this.chooseContextForm.get('namefield');
|
return this.chooseContextForm.get('namefield');
|
||||||
}
|
}
|
||||||
get uidfield(): any {
|
get uidfield(): any {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return this.chooseContextForm.get('uidfield');
|
return this.chooseContextForm.get('uidfield');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
onSubmit(): void {
|
|
||||||
console.log(this.chooseContextForm.value);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
/*
|
|
||||||
this.myForm = this.formBuilder.group({
|
|
||||||
context: [],});
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.resLoader.getResourcesByContext().subscribe(res => {
|
this.resLoader.getResourcesByContext().subscribe(res => {
|
||||||
this.nestedDataSource.data = res;
|
this.nestedDataSource.data = res;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.chooseContextForm = this.fb.group({
|
||||||
|
namefield: null,
|
||||||
|
uidfield: null,
|
||||||
|
});
|
||||||
|
|
||||||
// per la form dei contesti
|
// per la form dei contesti
|
||||||
this.ctxLoader.getData().subscribe(res => {
|
this.ctxLoader.getData().subscribe(res => {
|
||||||
this.allContexts = res;
|
this.contexts = res;
|
||||||
console.log('*******numero contesti...', res.length);
|
console.log('*******numero contesti...', res.length);
|
||||||
});
|
});
|
||||||
this.filteredContexts = this.chooseContextForm.get('namefield')?.valueChanges.pipe(
|
|
||||||
|
this.filteredContexts = this.chooseContextForm.get('namefield').valueChanges.pipe(
|
||||||
startWith(''),
|
startWith(''),
|
||||||
map(name => (name ? this.doFilter(name) : this.allContexts.slice()))
|
map(ctx => (ctx ? this.filterContexts(ctx) : this.contexts.slice()))
|
||||||
);
|
);
|
||||||
|
} //fine oninit
|
||||||
|
|
||||||
|
//mettere ANY come tipo dell'argomento per evitare errore TypeScript nella map!!
|
||||||
|
filterContexts(name: any): IContextNode[] {
|
||||||
|
return this.contexts.filter(ctx => ctx.name.toLowerCase().includes(name.toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
displayFn(name: string): string {
|
||||||
|
return name ? name : '';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this.myForm = this.formBuilder.group({
|
//mettendo ID come value da passare
|
||||||
context: [],
|
displayFn(name: string): string {
|
||||||
});
|
if (!id) return '';
|
||||||
|
let index = this.states.findIndex(state => state.id === id);
|
||||||
*/
|
return this.states[index].name;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
hasNestedChild(_: number, node: IResource): boolean {
|
hasNestedChild(_: number, node: IResource): boolean {
|
||||||
if (node.children == null) {
|
if (node.children == null) {
|
||||||
|
@ -79,24 +84,4 @@ export class RscTreeComponent implements OnInit {
|
||||||
return node.children.length > 0;
|
return node.children.length > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private doFilter(name: string): IContextNode[] {
|
|
||||||
//return this.allContexts.filter(ctx => ctx.name.toLowerCase().includes(name.toLowerCase()));
|
|
||||||
return this.allContexts.filter(ctx => ctx.name.toLowerCase().includes(name.toLowerCase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
onEnter(evt: any){
|
|
||||||
if (evt.source.selected) {
|
|
||||||
alert("hello ");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
//TODO: modificare per gestire eventuali eventi sulla onselect
|
|
||||||
private onSelectedContext(uid:string):void {
|
|
||||||
this.resLoader.getResourcesByContext().subscribe(res => {
|
|
||||||
this.nestedDataSource.data = res;
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, map, tap } from 'rxjs';
|
||||||
import { appProperties } from 'app/config/app-properties';
|
import { appProperties } from 'app/config/app-properties';
|
||||||
import { IContextNode } from './i-context-node';
|
import { IContextNode } from './i-context-node';
|
||||||
|
|
||||||
|
@ -16,10 +16,9 @@ export class ContextsLoaderService {
|
||||||
|
|
||||||
getData(): Observable<IContextNode[]> {
|
getData(): Observable<IContextNode[]> {
|
||||||
//TODO: pipe per gestione errori
|
//TODO: pipe per gestione errori
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
||||||
// return this.http.get<IContextNode[]>(appProperties.BASEURL_API + 'is/allcontext');
|
|
||||||
return this.http.get<IContextNode[]>(appProperties.MOCK_BASEURL_API + '/allcontext');
|
return this.http.get<IContextNode[]>(appProperties.MOCK_BASEURL_API + '/allcontext');
|
||||||
}
|
}
|
||||||
|
|
||||||
getRawData(): Observable<string> {
|
getRawData(): Observable<string> {
|
||||||
//TODO: pipe per gestione errori
|
//TODO: pipe per gestione errori
|
||||||
return this.http.get<string>(appProperties.BASEURL_API + 'is/allcontext');
|
return this.http.get<string>(appProperties.BASEURL_API + 'is/allcontext');
|
||||||
|
|
|
@ -4,3 +4,17 @@ export interface IContextNode {
|
||||||
id: string;
|
id: string;
|
||||||
children?: IContextNode[];
|
children?: IContextNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ContextNode implements IContextNode {
|
||||||
|
parent: string;
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
children?: IContextNode[];
|
||||||
|
|
||||||
|
constructor(id: string, name: string, parent: string, children: ContextNode[]) {
|
||||||
|
this.name = name;
|
||||||
|
this.parent = id;
|
||||||
|
this.id = id;
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue