Revision 60310
Added by Konstantinos Triantafyllou about 3 years ago
input.component.ts | ||
---|---|---|
1 | 1 |
import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild} from "@angular/core"; |
2 |
import {AbstractControl} from "@angular/forms"; |
|
2 |
import {AbstractControl, FormArray, FormControl} from "@angular/forms";
|
|
3 | 3 |
import {HelperFunctions} from "../../utils/HelperFunctions.class"; |
4 |
import {Subscription} from "rxjs"; |
|
4 |
import {Observable, of, Subscription} from "rxjs";
|
|
5 | 5 |
import {MatSelect} from "@angular/material/select"; |
6 |
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete"; |
|
7 |
import {map, startWith} from "rxjs/operators"; |
|
6 | 8 |
|
7 | 9 |
|
8 | 10 |
export interface Option { |
... | ... | |
15 | 17 |
@Component({ |
16 | 18 |
selector: '[dashboard-input]', |
17 | 19 |
template: ` |
18 |
<div *ngIf="label && type != 'checkbox'" class="uk-text-bold uk-form-label uk-margin-small-bottom">{{label + (required ? ' *' : '')}}</div> |
|
20 |
<div *ngIf="label && type != 'checkbox'" |
|
21 |
class="uk-text-bold uk-form-label uk-margin-small-bottom">{{label + (required ? ' *' : '')}}</div> |
|
19 | 22 |
<div *ngIf="hint" class="uk-margin-bottom uk-text-small uk-form-hint">{{hint}}</div> |
20 | 23 |
<div class="uk-grid uk-flex uk-flex-middle" [class.uk-grid-small]="gridSmall" uk-grid> |
21 | 24 |
<ng-content></ng-content> |
22 |
<div [class.uk-hidden]="hideControl" class="uk-width-expand uk-position-relative" [class.uk-flex-first]="!extraLeft"> |
|
25 |
<div [class.uk-hidden]="hideControl" class="uk-width-expand uk-position-relative" |
|
26 |
[class.uk-flex-first]="!extraLeft"> |
|
23 | 27 |
<ng-template [ngIf]="icon && formControl.enabled"> |
24 | 28 |
<span class="uk-text-muted" [ngClass]="iconLeft?('left'):'right'"> |
25 | 29 |
<icon [name]="icon"></icon> |
... | ... | |
31 | 35 |
</span> |
32 | 36 |
</ng-template> |
33 | 37 |
<ng-template [ngIf]="type === 'text'"> |
34 |
<input class="uk-input input-box uk-text-small" [attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':''" [placeholder]="placeholder" [formControl]="formControl" |
|
38 |
<input class="uk-input input-box uk-text-small" |
|
39 |
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':''" |
|
40 |
[placeholder]="placeholder" [formControl]="formControl" |
|
35 | 41 |
[class.uk-form-danger]="formControl.invalid && formControl.touched"> |
36 | 42 |
</ng-template> |
37 | 43 |
<ng-template [ngIf]="type === 'textarea'"> |
38 |
<textarea class="uk-textarea input-box uk-text-small" [attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':''" [rows]="rows" [placeholder]="placeholder" |
|
44 |
<textarea class="uk-textarea input-box uk-text-small" |
|
45 |
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':''" |
|
46 |
[rows]="rows" [placeholder]="placeholder" |
|
39 | 47 |
[formControl]="formControl" [class.uk-form-danger]="formControl.invalid && formControl.touched"> |
40 | 48 |
</textarea> |
41 | 49 |
</ng-template> |
42 | 50 |
<ng-template [ngIf]="type === 'select'"> |
43 |
<div class="input-box" [attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null" [class.clickable]="formControl.enabled" [class.uk-form-danger]="formControl.invalid && formControl.touched" (click)="openSelect()"> |
|
51 |
<div class="input-box" |
|
52 |
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null" |
|
53 |
[class.clickable]="formControl.enabled" |
|
54 |
[class.uk-form-danger]="formControl.invalid && formControl.touched" (click)="openSelect()"> |
|
44 | 55 |
<mat-form-field class="uk-width-1-1"> |
45 |
<mat-select #select *ngIf="type === 'select'" [required]="required" [value]="null" |
|
46 |
(openedChange)="stopPropagation()" [formControl]="formControl" [disableOptionCentering]="true"> |
|
56 |
<mat-select #select [required]="required" [value]="null" |
|
57 |
(openedChange)="stopPropagation()" [formControl]="formControl" |
|
58 |
[disableOptionCentering]="true"> |
|
47 | 59 |
<mat-option *ngIf="placeholder" class="uk-hidden" [value]="''">{{placeholder}}</mat-option> |
48 | 60 |
<mat-option *ngFor="let option of options" [value]="option.value"> |
49 | 61 |
{{option.label}} |
... | ... | |
52 | 64 |
</mat-form-field> |
53 | 65 |
</div> |
54 | 66 |
</ng-template> |
55 |
<span *ngIf="formControl.invalid && formControl.errors.error" class="uk-text-danger input-message">{{formControl.errors.error}}</span> |
|
67 |
<ng-template [ngIf]="type === 'chips'"> |
|
68 |
<div class="input-box" |
|
69 |
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null" |
|
70 |
[class.clickable]="formControl.enabled" |
|
71 |
[class.uk-form-danger]="formControl.invalid && formControl.touched" (click)="openSelect()"> |
|
72 |
<mat-form-field class="uk-width-1-1"> |
|
73 |
<mat-chip-list #chipList aria-label="Page selection"> |
|
74 |
<mat-chip *ngFor="let chip of formAsArray.controls; let i=index" |
|
75 |
(removed)="removed(i)" |
|
76 |
[removable]="removable"> |
|
77 |
{{chip.value[chipLabel]}} |
|
78 |
<span (click)="removed(i)" |
|
79 |
class="mat-chip-remove mat-chip-trailing-icon" uk-icon="close"></span> |
|
80 |
</mat-chip> |
|
81 |
<div class="uk-width-expand uk-position-relative uk-text-small"> |
|
82 |
<input #searchInput class="uk-width-1-1" [formControl]="searchControl" [matAutocomplete]="auto" [matChipInputFor]="chipList"> |
|
83 |
<div *ngIf="placeholder && !searchControl.value" class="placeholder uk-width-1-1" |
|
84 |
(click)="searchInput.focus()">{{placeholder}}</div> |
|
85 |
</div> |
|
86 |
</mat-chip-list> |
|
87 |
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)"> |
|
88 |
<mat-option *ngFor="let option of filteredOptions | async" [value]="option.value"> |
|
89 |
{{option.label}} |
|
90 |
</mat-option> |
|
91 |
</mat-autocomplete> |
|
92 |
</mat-form-field> |
|
93 |
</div> |
|
94 |
</ng-template> |
|
95 |
<span *ngIf="formControl.invalid && formControl.errors.error" |
|
96 |
class="uk-text-danger input-message">{{formControl.errors.error}}</span> |
|
56 | 97 |
<span *ngIf="warning" class="uk-text-warning input-message">{{warning}}</span> |
57 | 98 |
<span *ngIf="note" class="input-message">{{note}}</span> |
58 | 99 |
</div> |
... | ... | |
63 | 104 |
}) |
64 | 105 |
export class InputComponent implements OnInit, OnDestroy, OnChanges { |
65 | 106 |
@Input('formInput') formControl: AbstractControl; |
66 |
@Input('type') type: 'text' | 'textarea' | 'select' | 'checkbox' = 'text'; |
|
107 |
@Input('type') type: 'text' | 'textarea' | 'select' | 'checkbox' | 'chips' = 'text';
|
|
67 | 108 |
@Input('label') label: string; |
68 | 109 |
@Input('rows') rows: number = 3; |
69 | 110 |
@Input('options') options: Option[]; |
... | ... | |
77 | 118 |
@Input() iconLeft: boolean = false; |
78 | 119 |
@Input() warning: string = null; |
79 | 120 |
@Input() note: string = null; |
121 |
@Input() removable: boolean = true; |
|
122 |
@Input() chipLabel: string = null; |
|
123 |
public filteredOptions: Observable<Option[]>; |
|
124 |
public searchControl: FormControl; |
|
80 | 125 |
public required: boolean = false; |
81 | 126 |
private initValue: any; |
82 | 127 |
private subscriptions: any[] = []; |
128 |
@ViewChild('searchInput') searchInput; |
|
83 | 129 |
|
84 | 130 |
constructor() { |
85 | 131 |
} |
... | ... | |
94 | 140 |
} |
95 | 141 |
} |
96 | 142 |
|
143 |
get formAsArray(): FormArray { |
|
144 |
return (<FormArray> this.formControl); |
|
145 |
} |
|
146 |
|
|
97 | 147 |
reset() { |
98 | 148 |
this.unsubscribe(); |
99 | 149 |
this.initValue = HelperFunctions.copy(this.formControl.value); |
150 |
if(this.options && this.type === 'chips') { |
|
151 |
this.filteredOptions = of(this.options); |
|
152 |
this.searchControl = new FormControl(''); |
|
153 |
this.filteredOptions = this.searchControl.valueChanges.pipe(startWith(''), |
|
154 |
map(option => this.filter(option))); |
|
155 |
} |
|
100 | 156 |
if (this.formControl && this.formControl.validator) { |
101 | 157 |
let validator = this.formControl.validator({} as AbstractControl); |
102 | 158 |
this.required = (validator && validator.required); |
... | ... | |
133 | 189 |
stopPropagation() { |
134 | 190 |
event.stopPropagation(); |
135 | 191 |
} |
192 |
|
|
193 |
removed(index: number) { |
|
194 |
this.formAsArray.removeAt(index); |
|
195 |
this.formAsArray.markAsDirty(); |
|
196 |
} |
|
197 |
|
|
198 |
selected(event: MatAutocompleteSelectedEvent): void { |
|
199 |
this.formAsArray.push(new FormControl(event.option.value)); |
|
200 |
this.formAsArray.markAsDirty(); |
|
201 |
this.searchControl.setValue(''); |
|
202 |
this.searchInput.nativeElement.value = ''; |
|
203 |
} |
|
204 |
|
|
205 |
private filter(value: string): Option[] { |
|
206 |
let options = this.options.filter(option => !this.formAsArray.value.find(value => option.label === value[this.chipLabel])); |
|
207 |
if (!value || value.length == 0) { |
|
208 |
return options; |
|
209 |
} |
|
210 |
const filterValue = value.toString().toLowerCase(); |
|
211 |
return options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1); |
|
212 |
} |
|
136 | 213 |
} |
Also available in: Unified diff
[Library | Trunk]: Admin tools pages, fix modals and update behaviour