Add new inputs modifiers. Add advanced-search-input.

This commit is contained in:
Konstantinos Triantafyllou 2022-04-04 11:06:34 +03:00
parent 1951ae8cdd
commit 225285c960
6 changed files with 124 additions and 56 deletions

View File

@ -42,12 +42,12 @@ declare var UIkit;
</div>
<div class="uk-width-expand">
<div #recipients dashboard-input type="chips" [options]="availableGroups" [showOptionsOnEmpty]="false"
class="uk-width-expand" (focusEmitter)="onFocus($event)" placeholder="Sent to"
class="uk-width-expand" (focusEmitter)="onFocus($event)" placeholder="Sent to" inputClass="none"
[formInput]="form.get('groups')">
</div>
<div dashboard-input [formInput]="form.get('message')"
[rows]="4" placeholder="Write a notification"
type="textarea" class="uk-margin-top">
type="textarea" class="uk-margin-top" inputClass="flat">
<div tools class="uk-margin-top uk-width-1-1 uk-flex uk-flex-right">
<button *ngIf="!sending && message" (click)="sendNotification()"
class="uk-button uk-button-small uk-button-secondary">Send</button>

View File

@ -0,0 +1,48 @@
import {
AfterContentInit,
Component,
ContentChildren,
EventEmitter,
Input,
OnDestroy,
Output,
QueryList
} from "@angular/core";
import {InputComponent} from "../input/input.component";
@Component({
selector: 'advanced-search-input',
template: `
<div class="advanced-search-input">
<div class="uk-grid uk-flex-middle" uk-grid>
<div class="uk-width-expand">
<div class="uk-grid uk-grid-collapse inputs" uk-grid>
<ng-content></ng-content>
</div>
</div>
<div class="uk-width-auto">
<div class="uk-margin-medium-right search" [class.disabled]="disabled" (click)="searchEmitter.emit()">
<icon name="search" [flex]="true"></icon>
</div>
</div>
</div>
</div>
`
})
export class AdvancedSearchInputComponent implements AfterContentInit, OnDestroy {
@ContentChildren(InputComponent) inputs: QueryList<InputComponent>
@Input() disabled: boolean = false;
@Output() searchEmitter: EventEmitter<void> = new EventEmitter<void>();
constructor() {
}
ngAfterContentInit() {
this.inputs.forEach(input => {
input.inputClass = 'advanced';
});
}
ngOnDestroy() {
}
}

View File

@ -0,0 +1,13 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {AdvancedSearchInputComponent} from "./advanced-search-input.component";
import {IconsModule} from "../../utils/icons/icons.module";
@NgModule({
imports: [CommonModule, IconsModule],
declarations: [AdvancedSearchInputComponent],
exports: [AdvancedSearchInputComponent]
})
export class AdvancedSearchInputModule {
}

View File

@ -1,5 +1,5 @@
import {
AfterViewInit,
AfterViewInit, ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
@ -18,6 +18,8 @@ import {Subscription} from "rxjs";
import {EnvProperties} from "../../utils/properties/env-properties";
import {properties} from "../../../../environments/environment";
export type InputType = 'text' | 'URL' | 'logoURL' | 'autocomplete' | 'textarea' | 'select' | 'chips';
export interface Option {
icon?: string,
iconClass?: string,
@ -39,12 +41,12 @@ declare var UIkit;
@Component({
selector: '[dashboard-input], [input]',
template: `
<div class="input-border" [class.disabled]="formControl.disabled"
<div class="input-wrapper" [class.disabled]="formControl.disabled" [class.opened]="opened"
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
[class.active]="(formAsControl?.value || formAsArray?.length > 0) && !focused"
[class.danger]="(formControl.invalid && (formControl.touched || searchControl?.touched)) || (searchControl?.invalid && searchControl?.touched)">
<div #inputBox class="input-wrapper" [class.static]="placeholderInfo.static"
[class.focused]="focused" [class.select]="type === 'select'"
[class.active]="(focused && type !== 'select') || formAsControl?.value || formAsArray?.length > 0 || hint"
[ngClass]="inputClass">
<div #inputBox class="input-box" [class.select]="type === 'select'"
[class.static]="placeholderInfo.static">
<div *ngIf="!placeholderInfo.static && placeholderInfo.label" class="placeholder">
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
</div>
@ -58,16 +60,14 @@ declare var UIkit;
[rows]="rows" [formControl]="formAsControl"></textarea>
</ng-template>
<ng-template [ngIf]="type === 'select'">
<div class="input">{{getLabel(formControl.value)}}</div>
<div *ngIf="formControl.value || !placeholderInfo.static" class="input">{{getLabel(formControl.value)}}</div>
<div *ngIf="!formControl.value && placeholderInfo.static" class="input placeholder">{{placeholderInfo.label}}</div>
</ng-template>
<ng-template [ngIf]="type === 'autocomplete'">
<div class="uk-grid uk-width-expand" uk-grid>
<div *ngIf="formControl.value">
<div class="input">{{getLabel(formControl.value)}}</div>
</div>
<div class="uk-width-expand">
<input [class.uk-hidden]="formControl.value" [attr.placeholder]="placeholderInfo.static?placeholderInfo.label:hint"
#searchInput class="input" [class.search]="searchControl.value" [formControl]="searchControl">
<input [attr.placeholder]="placeholderInfo.static?placeholderInfo.label:hint"
#searchInput class="input" [formControl]="searchControl">
</div>
</div>
</ng-template>
@ -76,23 +76,25 @@ declare var UIkit;
<div *ngFor="let chip of formAsArray.controls; let i=index" class="chip">
<div class="uk-label uk-flex uk-flex-middle">
<span class="uk-text-truncate uk-width-expand">{{getLabel(chip.value)}}</span>
<icon (click)="remove(i)" class="uk-link-text uk-margin-small-left clickable" [flex]="true"
<icon (click)="remove(i, $event)" class="uk-link-text uk-margin-small-left clickable" [flex]="true"
name="close" ratio="0.7"></icon>
</div>
</div>
<div class="uk-width-expand uk-flex uk-flex-column uk-flex-center">
<input #searchInput class="input" [class.search]="searchControl.value"
[attr.placeholder]="placeholderInfo.static?placeholderInfo.label:hint" [formControl]="searchControl">
[attr.placeholder]="placeholderInfo.static?placeholderInfo.label:hint"
[formControl]="searchControl">
</div>
</div>
</ng-template>
<div *ngIf="formControl.disabled || icon || type === 'select' || type === 'autocomplete'"
<div *ngIf="formControl.disabled || icon || (type === 'select' && selectArrow) || type === 'autocomplete'"
class="uk-margin-small-left uk-margin-right icon">
<icon *ngIf="formControl.disabled" [name]="'lock'" [flex]="true"></icon>
<ng-template [ngIf]="formControl.enabled">
<icon *ngIf="!formControl.value && icon" [name]="icon" [flex]="true"></icon>
<icon *ngIf="!icon && type === 'select'" name="arrow_drop_down" [flex]="true"></icon>
<icon *ngIf="formControl.value && type === 'autocomplete'" class="clickable" (click)="resetSearch($event)" [flex]="true" name="close"></icon>
<icon *ngIf="!icon && type === 'select' && selectArrow" name="arrow_drop_down" [flex]="true"></icon>
<icon *ngIf="formControl.value && type === 'autocomplete'" class="clickable" (click)="resetSearch($event)"
[flex]="true" name="close"></icon>
</ng-template>
</div>
</div>
@ -101,10 +103,11 @@ declare var UIkit;
</div>
</div>
</div>
<div class="options uk-dropdown" *ngIf="filteredOptions && filteredOptions.length > 1 && opened" #optionBox
uk-dropdown="pos: bottom-justify; mode: hover; offset: 15;">
<div class="options uk-dropdown" *ngIf="filteredOptions && filteredOptions.length > 0 && opened" #optionBox
uk-dropdown="pos: bottom-justify; mode: click; offset: 15;">
<ul class="uk-nav uk-dropdown-nav">
<li *ngFor="let option of filteredOptions" [class.uk-active]="formControl.value === option.value" [attr.uk-tooltip]="(tooltip)?('title: ' + option.label + ';'):null">
<li *ngFor="let option of filteredOptions" [class.uk-active]="formControl.value === option.value"
[attr.uk-tooltip]="(tooltip)?('title: ' + option.label + ';'):null">
<a (click)="selectOption(option, $event)">{{option.label}}</a>
</li>
</ul>
@ -153,7 +156,9 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@Input() panelClass: string = null;
/** Basic information */
@Input('formInput') formControl: AbstractControl;
@Input('type') type: 'text' | 'URL' | 'logoURL' | 'autocomplete' | 'textarea' | 'select' | 'chips' = 'text';
@Input('type') type: InputType = 'text';
@Input() validators: ValidatorFn[] | ValidatorFn;
@Input() disabled: boolean = false;
@Input() value: any | any[];
@Output() valueChange = new EventEmitter<any | any[]>();
@Input('hint') hint: string;
@ -165,6 +170,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
/** Select | Autocomplete | chips available options */
@Input('options') options: Option[] = [];
@Input() tooltip: boolean = false;
@Input() selectArrow: string = 'arrow_drop_down';
/** Chips && Autocomplete*/
public filteredOptions: Option[] = [];
public searchControl: FormControl;
@ -175,8 +181,6 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
/** Chip options */
@Input() addExtraChips: boolean = false;
@Input() showOptionsOnEmpty: boolean = true;
@Input() validators: ValidatorFn[] | ValidatorFn;
@Input() disabled: boolean = false;
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
/** LogoUrl information */
public secure: boolean = true;
@ -194,10 +198,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@Input()
set placeholder(placeholder: string | Placeholder) {
if(typeof placeholder === 'string') {
if (typeof placeholder === 'string') {
this.placeholderInfo = {label: placeholder, static: false};
} else {
if(placeholder.static && (this.type === 'select' || this.type === 'autocomplete' || this.type === 'chips' || this.hint)) {
if (placeholder.static && (this.type === 'autocomplete' || this.type === 'chips' || this.hint)) {
placeholder.static = false;
console.debug('Static placeholder is not available in this type of input and if hint is available.');
}
@ -205,7 +209,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
}
constructor(private elementRef: ElementRef) {
constructor(private elementRef: ElementRef, private cdr: ChangeDetectorRef) {
if (elementRef.nativeElement.hasAttribute('dashboard-input') && this.properties.environment === "development") {
console.warn("'dashboard-input' selector is deprecated; use 'input' instead.");
}
@ -213,7 +217,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
@HostListener('document:click', ['$event'])
click(event) {
this.focus(this.inputBox && this.inputBox.nativeElement.contains(event.target));
this.focus(this.inputBox && this.inputBox.nativeElement.contains(event.target), event);
}
ngOnInit() {
@ -238,6 +242,9 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
ngOnChanges(changes: SimpleChanges) {
if(changes.value && this.formControl) {
this.formControl.setValue(this.value);
}
if (changes.formControl || changes.validators || changes.options) {
this.reset();
}
@ -274,7 +281,10 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.filteredOptions = this.filter('');
}
if (this.type === 'chips' || this.type === 'autocomplete') {
this.searchControl = new FormControl('', this.validators);
if (!this.searchControl) {
this.searchControl = new FormControl('', this.validators);
}
this.searchControl.setValue(this.getLabel(this.formControl.value));
this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
this.filteredOptions = this.filter(value);
if (this.focused) {
@ -301,7 +311,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
this.formControl.markAsDirty();
}
if (this.searchControl) {
this.searchControl.setValue(null);
this.searchControl.setValue(this.type === 'autocomplete' ? this.getLabel(this.formControl.value) : null);
}
this.value = this.formControl.value;
this.valueChange.emit(this.value);
@ -323,12 +333,12 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
event.stopPropagation();
}
remove(index: number) {
remove(index: number, event) {
this.formAsArray.removeAt(index);
this.formAsArray.markAsDirty();
this.focus(true);
this.searchControl.setValue('');
this.stopPropagation();
event.stopPropagation();
}
private filter(value: string): Option[] {
@ -340,12 +350,15 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
return (this.showOptionsOnEmpty) ? options : [];
}
const filterValue = value.toString().toLowerCase();
console.log(options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1));
return options.filter(option => option.label.toLowerCase().indexOf(filterValue) != -1);
}
add() {
add(event) {
if (this.addExtraChips && this.searchControl.value && this.searchControl.valid) {
this.stopPropagation();
if (event) {
event.stopPropagation();
}
this.formAsArray.push(new FormControl(this.searchControl.value, this.validators));
this.formAsArray.markAsDirty();
this.focus(true);
@ -355,11 +368,11 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
getLabel(value: any) {
let option = this.options.find(option => HelperFunctions.equals(option.value, value));
return (option) ? option.label : value;
return (option) ? option.label : (value);
}
focus(value: boolean) {
if(this.focused) {
focus(value: boolean, event = null) {
if (this.focused) {
this.formControl.markAsTouched();
}
this.focused = value;
@ -379,7 +392,8 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
} else {
this.open(false);
if (this.searchControl) {
this.add();
this.searchControl.setValue(this.getLabel(this.formControl.value));
this.add(event);
}
}
this.focusEmitter.emit(this.focused);
@ -387,15 +401,14 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
open(value: boolean) {
this.opened = value && this.formControl.enabled;
setTimeout(() => {
if(this.optionBox) {
if (this.opened) {
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
UIkit.dropdown(this.optionBox.nativeElement).hide();
}
this.cdr.detectChanges();
if (this.optionBox) {
if (this.opened) {
UIkit.dropdown(this.optionBox.nativeElement).show();
} else {
UIkit.dropdown(this.optionBox.nativeElement).hide();
}
}, 0);
}
}
resetSearch(event: any) {
@ -407,7 +420,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
}
selectOption(option: Option, event) {
if(this.formControl.enabled) {
if (this.formControl.enabled) {
if (this.formAsControl) {
this.formAsControl.setValue(option.value);
} else if (this.formAsArray) {

View File

@ -3,16 +3,10 @@ import {SharedModule} from '../../shared/shared.module';
import {SearchInputComponent} from './search-input.component';
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import {IconsModule} from '../../utils/icons/icons.module';
import {IconsService} from '../../utils/icons/icons.service';
import {close, search} from '../../utils/icons/icons';
@NgModule({
imports: [SharedModule, MatAutocompleteModule, IconsModule],
declarations: [SearchInputComponent],
exports: [SearchInputComponent]
})
export class SearchInputModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([search, close]);
}
}
export class SearchInputModule {}

View File

@ -1,4 +1,4 @@
import {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild} from "@angular/core";
import {AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, ViewChild} from "@angular/core";
import {IconsService} from "./icons.service";
export interface StopRule {