Click outside optimized and use at input and search-input
This commit is contained in:
parent
901078ea42
commit
e6b2f41c8c
|
@ -17,6 +17,7 @@ import {HelperFunctions} from "../../utils/HelperFunctions.class";
|
|||
import {Subscription} from "rxjs";
|
||||
import {EnvProperties} from "../../utils/properties/env-properties";
|
||||
import {properties} from "../../../../environments/environment";
|
||||
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
|
||||
|
||||
export type InputType = 'text' | 'URL' | 'logoURL' | 'autocomplete' | 'autocomplete_soft' | 'textarea' | 'select' | 'chips';
|
||||
|
||||
|
@ -49,8 +50,8 @@ declare var UIkit;
|
|||
[class.focused]="focused" [ngClass]="inputClass" [class.hint]="hint"
|
||||
[class.active]="(formAsControl?.value || formAsArray?.length > 0 || getLabel(formAsControl?.value)) && !focused"
|
||||
[class.danger]="(formControl.invalid && (formControl.touched || searchControl?.touched)) || (searchControl?.invalid && searchControl?.touched)">
|
||||
<div #inputBox class="input-box" [class.select]="type === 'select'"
|
||||
[class.static]="placeholderInfo?.static">
|
||||
<div #inputBox class="input-box" [class.select]="type === 'select'" click-outside-or-esc
|
||||
[class.static]="placeholderInfo?.static" (clickOutside)="click($event)">
|
||||
<div *ngIf="!placeholderInfo?.static && placeholderInfo.label" class="placeholder">
|
||||
<label>{{placeholderInfo.label}} <sup *ngIf="required">*</sup></label>
|
||||
</div>
|
||||
|
@ -267,11 +268,8 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
|
|||
}
|
||||
}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
click(event) {
|
||||
if(event.isTrusted) {
|
||||
this.focus(this.inputBox && this.inputBox.nativeElement.contains(event.target), event);
|
||||
}
|
||||
click(event: ClickEvent) {
|
||||
this.focus(!event.clicked, event);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -401,11 +399,7 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
stopPropagation() {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
|
||||
remove(index: number, event) {
|
||||
this.formAsArray.removeAt(index);
|
||||
this.formAsArray.markAsDirty();
|
||||
|
@ -439,7 +433,6 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
|
|||
}
|
||||
this.formAsArray.push(new FormControl(this.searchControl.value, this.validators));
|
||||
this.formAsArray.markAsDirty();
|
||||
this.focus(true);
|
||||
}
|
||||
this.searchControl.setValue('');
|
||||
}
|
||||
|
@ -470,6 +463,13 @@ export class InputComponent implements OnInit, OnDestroy, AfterViewInit, OnChang
|
|||
}
|
||||
} else {
|
||||
this.open(false);
|
||||
if (this.input) {
|
||||
this.input.nativeElement.blur();
|
||||
} else if (this.textArea) {
|
||||
this.textArea.nativeElement.blur();
|
||||
} else if (this.searchInput) {
|
||||
this.searchInput.nativeElement.blur();
|
||||
}
|
||||
if (this.searchControl) {
|
||||
this.add(event);
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@ import {InputComponent} from "./input.component";
|
|||
import {SharedModule} from "../../shared/shared.module";
|
||||
import {IconsModule} from "../../utils/icons/icons.module";
|
||||
import {SafeHtmlPipeModule} from "../../utils/pipes/safeHTMLPipe.module";
|
||||
import {ClickModule} from "../../utils/click/click.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SharedModule,
|
||||
IconsModule,
|
||||
SafeHtmlPipeModule
|
||||
SafeHtmlPipeModule,
|
||||
ClickModule
|
||||
],
|
||||
exports: [
|
||||
InputComponent
|
||||
|
|
|
@ -12,16 +12,17 @@ import {
|
|||
import {AbstractControl} from '@angular/forms';
|
||||
import {MatAutocompleteTrigger} from '@angular/material/autocomplete';
|
||||
import {InputComponent} from "../input/input.component";
|
||||
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";
|
||||
|
||||
@Component({
|
||||
selector: '[search-input]',
|
||||
template: `
|
||||
<div class="uk-flex uk-flex-right uk-width-1-1">
|
||||
<div #searchInput class="search-input" [class.collapsed]="hidden" [ngClass]="searchInputClass">
|
||||
<div #searchInput click-outside-or-esc (clickOutside)="click($event)" class="search-input" [class.collapsed]="hidden" [ngClass]="searchInputClass">
|
||||
<div class="uk-flex uk-flex-middle">
|
||||
<div class="uk-width-expand">
|
||||
<div #input [class.uk-hidden]="hidden" input [formInput]="searchControl" inputClass="search" [disabledIcon]="null"
|
||||
[placeholder]="{label: placeholder, static: true}" [(value)]="value" (valueChange)="valueChange.emit($event)"
|
||||
[placeholder]="{label: placeholder, static: true}" [value]="value" (valueChange)="valueChange.emit($event)"
|
||||
[disabled]="disabled" [type]="(options.length > 0?'autocomplete_soft':'text')" [options]="options"></div>
|
||||
</div>
|
||||
<div [class.uk-hidden]="(!searchControl?.value && !value) || disabled" class="uk-width-auto">
|
||||
|
@ -66,10 +67,9 @@ export class SearchInputComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
click(event) {
|
||||
if(event.isTrusted && this.expandable && !this.disabled) {
|
||||
this.expand(this.searchInput && this.searchInput.nativeElement.contains(event.target));
|
||||
click(event: ClickEvent) {
|
||||
if(this.expandable && !this.disabled) {
|
||||
this.expand(!event.clicked);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@ import {SearchInputComponent} from './search-input.component';
|
|||
import {MatAutocompleteModule} from '@angular/material/autocomplete';
|
||||
import {IconsModule} from '../../utils/icons/icons.module';
|
||||
import {InputModule} from "../input/input.module";
|
||||
import {ClickModule} from "../../utils/click/click.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, MatAutocompleteModule, IconsModule, InputModule],
|
||||
imports: [SharedModule, MatAutocompleteModule, IconsModule, InputModule, ClickModule],
|
||||
declarations: [SearchInputComponent],
|
||||
exports: [SearchInputComponent]
|
||||
})
|
||||
|
|
|
@ -1,79 +1,35 @@
|
|||
import {Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
|
||||
import {fromEvent, Subscriber} from 'rxjs';
|
||||
import {delay, tap} from 'rxjs/operators';
|
||||
import {Directive, ElementRef, EventEmitter, HostListener, Output} from '@angular/core';
|
||||
|
||||
export interface ClickEvent {
|
||||
event: any,
|
||||
clicked: boolean;
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: '[click-outside-or-esc]'
|
||||
})
|
||||
export class ClickOutsideOrEsc {
|
||||
@Output('clickOutside') clickOutside: EventEmitter<ClickEvent> = new EventEmitter<ClickEvent>();
|
||||
|
||||
export class ClickOutsideOrEsc implements OnInit, OnDestroy {
|
||||
private listening: boolean;
|
||||
private subscriptions: any[] = [];
|
||||
@Input()
|
||||
public targetId = null;
|
||||
@Input()
|
||||
public escClose = true;
|
||||
@Input()
|
||||
public clickClose = true;
|
||||
@Output('clickOutside') clickOutside: EventEmitter<Object>;
|
||||
|
||||
constructor(private _elRef: ElementRef) {
|
||||
this.listening = false;
|
||||
this.clickOutside = new EventEmitter();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if(typeof document !== 'undefined') {
|
||||
this.subscriptions.push(fromEvent(document, 'click').pipe(
|
||||
delay(1),
|
||||
tap(() => {
|
||||
this.listening = true;
|
||||
})).subscribe((event: MouseEvent) => {
|
||||
this.onGlobalClick(event);
|
||||
}));
|
||||
this.subscriptions.push(fromEvent(document, 'click').pipe(
|
||||
delay(1),
|
||||
tap(() => {
|
||||
this.listening = true;
|
||||
})).subscribe((event: KeyboardEvent) => {
|
||||
if (event.keyCode === 27 && this.escClose) {
|
||||
this.clickOutside.emit({
|
||||
target: (event.target || null),
|
||||
value: true
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.subscriptions) {
|
||||
this.subscriptions.forEach((subscription: Subscriber<any>) => {
|
||||
subscription.unsubscribe();
|
||||
constructor(private elementRef: ElementRef) {}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
click(event) {
|
||||
if(event.isTrusted) {
|
||||
this.clickOutside.emit({
|
||||
event: event,
|
||||
clicked: !(this.elementRef && this.elementRef.nativeElement.contains(event.target))
|
||||
});
|
||||
}
|
||||
this.subscriptions = [];
|
||||
}
|
||||
|
||||
onGlobalClick(event: MouseEvent) {
|
||||
if (event instanceof MouseEvent && this.listening === true) {
|
||||
let element: HTMLElement = <HTMLElement>event.target;
|
||||
while (element) {
|
||||
if(element.id === this.targetId) {
|
||||
this.clickOutside.emit({
|
||||
target: (event.target || null),
|
||||
value: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
element = element.parentElement;
|
||||
}
|
||||
if(this.clickClose) {
|
||||
this.clickOutside.emit({
|
||||
target: (event.target || null),
|
||||
value: true
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
keyEvent(event: KeyboardEvent) {
|
||||
if(event.code === 'Escape') {
|
||||
this.clickOutside.emit({
|
||||
event: event,
|
||||
clicked: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue