fixed multiple autocomplete panel behavior
This commit is contained in:
parent
30d338bbbd
commit
7022de0bc8
|
@ -21,62 +21,64 @@
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<input matInput #autocompleteInput [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" autocomplete="off" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)">
|
<input matInput #autocompleteInput [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" autocomplete="off" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)">
|
||||||
</div>
|
</div>
|
||||||
<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="_displayFn.bind(this)" (optionSelected)="_optionSelected($event)">
|
<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="_displayFn.bind(this)" (optionSelected)="_optionSelected($event)" [classList]="['myClass']">
|
||||||
<span *ngIf="_groupedItems">
|
<div (mouseover)="isMouseOverPanel=true" (mouseout)="isMouseOverPanel=false">
|
||||||
<mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title">
|
<span *ngIf="_groupedItems">
|
||||||
<mat-option *ngFor="let item of group.items" [value]="item" class="option" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)">
|
<mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title">
|
||||||
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
|
<mat-option *ngFor="let item of group.items" [value]="item" class="option" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)" (optionActivated)="clickedOnPanel()">
|
||||||
<ng-container *ngIf="_optionComponent(item)">
|
|
||||||
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
|
|
||||||
</ng-container>
|
|
||||||
<ng-template #cellTemplate *ngIf="_optionTemplate(item) && !_optionComponent(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
|
||||||
item: item
|
|
||||||
}"></ng-template>
|
|
||||||
<div *ngIf="!_optionTemplate(item)" class="d-flex">
|
|
||||||
<div class="title-subtitle-fn">
|
|
||||||
<div class="title-fn">
|
|
||||||
<div class="title-fn-inner">
|
|
||||||
<span *ngIf="!_optionTemplate(item)" class="title-text">{{_titleFn(item)}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="_subtitleFn(item)" class="subtitle-fn">
|
|
||||||
<div class="subtitle-fn-inner">
|
|
||||||
<small [innerHTML]="_subtitleFn(item)" class="subtitle-text"></small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
|
||||||
</div>
|
|
||||||
</mat-option>
|
|
||||||
</mat-optgroup>
|
|
||||||
</span>
|
|
||||||
<span *ngIf="!_groupedItems">
|
|
||||||
<div *ngIf="_items | async as autocompleteItems; else loading">
|
|
||||||
<ng-container *ngIf="autocompleteItems.length; else noItems">
|
|
||||||
<mat-option *ngFor="let item of autocompleteItems" class="option" [value]="item" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)">
|
|
||||||
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
|
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
|
||||||
<ng-container *ngIf="_optionComponent(item)">
|
<ng-container *ngIf="_optionComponent(item)">
|
||||||
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
|
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #cellTemplate *ngIf="_optionTemplate(item) && !_optionComponent(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
<ng-template #cellTemplate *ngIf="_optionTemplate(item) && !_optionComponent(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
||||||
item: item
|
item: item
|
||||||
}"></ng-template>
|
}"></ng-template>
|
||||||
<div *ngIf="!_optionTemplate(item) && !_optionComponent(item)">
|
<div *ngIf="!_optionTemplate(item)" class="d-flex">
|
||||||
<span class="title-text">{{_titleFn(item)}}</span>
|
<div class="title-subtitle-fn">
|
||||||
<br *ngIf="_subtitleFn(item)">
|
<div class="title-fn">
|
||||||
<small *ngIf="_subtitleFn(item)" class="subtitle-text">{{_subtitleFn(item)}}</small>
|
<div class="title-fn-inner">
|
||||||
|
<span *ngIf="!_optionTemplate(item)" class="title-text">{{_titleFn(item)}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="_subtitleFn(item)" class="subtitle-fn">
|
||||||
|
<div class="subtitle-fn-inner">
|
||||||
|
<small [innerHTML]="_subtitleFn(item)" class="subtitle-text"></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
||||||
</div>
|
</div>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</ng-container>
|
</mat-optgroup>
|
||||||
<ng-template #noItems>
|
</span>
|
||||||
<mat-option disabled="true">No results found!</mat-option>
|
<span *ngIf="!_groupedItems">
|
||||||
|
<div *ngIf="_items | async as autocompleteItems; else loading">
|
||||||
|
<ng-container *ngIf="autocompleteItems.length; else noItems">
|
||||||
|
<mat-option *ngFor="let item of autocompleteItems" class="option" [value]="item" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)" (optionActivated)="clickedOnPanel()">
|
||||||
|
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
|
||||||
|
<ng-container *ngIf="_optionComponent(item)">
|
||||||
|
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #cellTemplate *ngIf="_optionTemplate(item) && !_optionComponent(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
|
||||||
|
item: item
|
||||||
|
}"></ng-template>
|
||||||
|
<div *ngIf="!_optionTemplate(item) && !_optionComponent(item)">
|
||||||
|
<span class="title-text">{{_titleFn(item)}}</span>
|
||||||
|
<br *ngIf="_subtitleFn(item)">
|
||||||
|
<small *ngIf="_subtitleFn(item)" class="subtitle-text">{{_subtitleFn(item)}}</small>
|
||||||
|
<span *ngIf="popupItemActionIcon" class="option-icon" (click)="_optionActionClick(item, $event)"><mat-icon>{{popupItemActionIcon}}</mat-icon></span>
|
||||||
|
</div>
|
||||||
|
</mat-option>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #noItems>
|
||||||
|
<mat-option disabled="true">No results found!</mat-option>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
<ng-template #loading>
|
||||||
|
<mat-option disabled="true">loading...</mat-option>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</span>
|
||||||
<ng-template #loading>
|
</div>
|
||||||
<mat-option disabled="true">loading...</mat-option>
|
|
||||||
</ng-template>
|
|
||||||
</span>
|
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,22 +1,6 @@
|
||||||
import { FocusMonitor } from '@angular/cdk/a11y';
|
import { FocusMonitor } from '@angular/cdk/a11y';
|
||||||
import { ENTER } from '@angular/cdk/keycodes';
|
import { ENTER } from '@angular/cdk/keycodes';
|
||||||
import {
|
import { Component, DoCheck, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Optional, Output, Self, SimpleChanges, TemplateRef, Type, ViewChild } from '@angular/core';
|
||||||
Component,
|
|
||||||
DoCheck,
|
|
||||||
ElementRef,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
OnChanges,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit,
|
|
||||||
Optional,
|
|
||||||
Output,
|
|
||||||
Self,
|
|
||||||
SimpleChanges,
|
|
||||||
TemplateRef,
|
|
||||||
Type,
|
|
||||||
ViewChild
|
|
||||||
} from '@angular/core';
|
|
||||||
import { ControlValueAccessor, FormGroupDirective, NgControl, NgForm } from '@angular/forms';
|
import { ControlValueAccessor, FormGroupDirective, NgControl, NgForm } from '@angular/forms';
|
||||||
import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
||||||
import { MatChipInputEvent } from '@angular/material/chips';
|
import { MatChipInputEvent } from '@angular/material/chips';
|
||||||
|
@ -27,7 +11,7 @@ import {
|
||||||
MultipleAutoCompleteConfiguration
|
MultipleAutoCompleteConfiguration
|
||||||
} from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
} from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
||||||
import { BaseComponent } from '@common/base/base.component';
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
import { BehaviorSubject, Observable, Subject, interval, of as observableOf, of } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject, Subscription, interval, of as observableOf, of } from 'rxjs';
|
||||||
import { catchError, debounceTime, delayWhen, distinctUntilChanged, map, mergeMap, startWith, switchMap, take, takeUntil } from 'rxjs/operators';
|
import { catchError, debounceTime, delayWhen, distinctUntilChanged, map, mergeMap, startWith, switchMap, take, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
export class CustomComponentBase extends BaseComponent {
|
export class CustomComponentBase extends BaseComponent {
|
||||||
|
@ -98,6 +82,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
||||||
selectable = false;
|
selectable = false;
|
||||||
selected: boolean = false;
|
selected: boolean = false;
|
||||||
|
|
||||||
|
isMouseOverPanel: boolean = false;
|
||||||
|
panelClosedSubscription: Subscription;
|
||||||
|
|
||||||
get empty() {
|
get empty() {
|
||||||
return (!this.value || this.value.length === 0) && (!this.inputValue || this.inputValue.length === 0);
|
return (!this.value || this.value.length === 0) && (!this.inputValue || this.inputValue.length === 0);
|
||||||
}
|
}
|
||||||
|
@ -182,9 +169,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
||||||
this.focused = !!origin;
|
this.focused = !!origin;
|
||||||
this.stateChanges.next();
|
this.stateChanges.next();
|
||||||
|
|
||||||
// if (!this.focused) {
|
if (!this.isMouseOverPanel && !this.focused) {
|
||||||
// this.autocompleteTrigger?.closePanel();
|
this.autocompleteTrigger?.closePanel();
|
||||||
// }
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.ngControl != null) {
|
if (this.ngControl != null) {
|
||||||
|
@ -194,7 +181,11 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() { }
|
ngOnInit() {
|
||||||
|
this.panelClosedSubscription = this.autocomplete.closed.subscribe((next) => {
|
||||||
|
this.isMouseOverPanel=false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ngDoCheck(): void {
|
ngDoCheck(): void {
|
||||||
if (this.ngControl) {
|
if (this.ngControl) {
|
||||||
|
@ -358,6 +349,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
|
||||||
this.stateChanges.complete();
|
this.stateChanges.complete();
|
||||||
this.fm.stopMonitoring(this.elRef.nativeElement);
|
this.fm.stopMonitoring(this.elRef.nativeElement);
|
||||||
this.gettingSelectedItem$.complete();
|
this.gettingSelectedItem$.complete();
|
||||||
|
this.panelClosedSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Configuration getters
|
//Configuration getters
|
||||||
|
|
|
@ -395,7 +395,7 @@
|
||||||
|
|
||||||
.stepper-actions {
|
.stepper-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 1rem;
|
// padding-left: 1rem;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
// margin-top: 5rem;
|
// margin-top: 5rem;
|
||||||
|
|
Loading…
Reference in New Issue