Merge pull request #5684 from tsiegleauq/vscroll-selection-bugs
Fix a bug where vscroll select lists lost content
This commit is contained in:
commit
22f9108b49
@ -3,7 +3,17 @@
|
||||
[multiple]="multiple"
|
||||
[panelClass]="{ 'os-search-value-selector': multiple }"
|
||||
[errorStateMatcher]="errorStateMatcher"
|
||||
(openedChange)="openSelect($event)"
|
||||
>
|
||||
<!-- Custom display of selected items -->
|
||||
<mat-select-trigger>
|
||||
<ng-container *ngIf="selectedItems?.length">
|
||||
<span *ngFor="let item of selectedItems; let i = index">
|
||||
{{ item.getTitle() | translate }}<span *ngIf="i < selectedItems.length - 1">, </span>
|
||||
</span>
|
||||
</ng-container>
|
||||
</mat-select-trigger>
|
||||
|
||||
<mat-option>
|
||||
<ngx-mat-select-search [formControl]="searchValue"></ngx-mat-select-search>
|
||||
</mat-option>
|
||||
@ -14,7 +24,7 @@
|
||||
<mat-chip
|
||||
*ngFor="let item of selectedItems"
|
||||
[removable]="true"
|
||||
(removed)="removeItem(item.id)"
|
||||
(removed)="removeChipItem(item)"
|
||||
[disableRipple]="true"
|
||||
>
|
||||
{{ item.getTitle() | translate }}
|
||||
@ -36,8 +46,12 @@
|
||||
</mat-option>
|
||||
<mat-divider></mat-divider>
|
||||
</ng-container>
|
||||
<cdk-virtual-scroll-viewport class="vscroll-viewport" minBufferPx="200" maxBufferPx="300" [itemSize]="50">
|
||||
<mat-option *cdkVirtualFor="let selectedItem of getFilteredItems()" [value]="selectedItem.id">
|
||||
<cdk-virtual-scroll-viewport class="vscroll-viewport" minBufferPx="400" maxBufferPx="600" [itemSize]="50">
|
||||
<mat-option
|
||||
*cdkVirtualFor="let selectedItem of getFilteredItems()"
|
||||
[value]="selectedItem.id"
|
||||
(onSelectionChange)="onSelectionChange($event)"
|
||||
>
|
||||
{{ selectedItem.getTitle() | translate }}
|
||||
</mat-option>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { FocusMonitor } from '@angular/cdk/a11y';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@ -12,6 +13,7 @@ import {
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { FormBuilder, FormControl, NgControl } from '@angular/forms';
|
||||
import { MatOptionSelectionChange } from '@angular/material/core';
|
||||
import { MatFormFieldControl } from '@angular/material/form-field';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -19,6 +21,7 @@ import { Observable } from 'rxjs';
|
||||
import { auditTime } from 'rxjs/operators';
|
||||
|
||||
import { BaseFormControlComponentDirective } from 'app/shared/models/base/base-form-control';
|
||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||
import { ParentErrorStateMatcher } from 'app/shared/parent-error-state-matcher';
|
||||
import { Selectable } from '../selectable';
|
||||
|
||||
@ -55,6 +58,9 @@ export class SearchValueSelectorComponent extends BaseFormControlComponentDirect
|
||||
@ViewChild('chipPlaceholder', { static: false })
|
||||
public chipPlaceholder: ElementRef<HTMLElement>;
|
||||
|
||||
@ViewChild(CdkVirtualScrollViewport, { static: true })
|
||||
public cdkVirtualScrollViewPort: CdkVirtualScrollViewport;
|
||||
|
||||
/**
|
||||
* Decide if this should be a single or multi-select-field
|
||||
*/
|
||||
@ -134,6 +140,8 @@ export class SearchValueSelectorComponent extends BaseFormControlComponentDirect
|
||||
*/
|
||||
private selectableItems: Selectable[];
|
||||
|
||||
public selectedIds: number[] = [];
|
||||
|
||||
public constructor(
|
||||
protected translate: TranslateService,
|
||||
formBuilder: FormBuilder,
|
||||
@ -144,6 +152,13 @@ export class SearchValueSelectorComponent extends BaseFormControlComponentDirect
|
||||
super(formBuilder, focusMonitor, element, ngControl);
|
||||
}
|
||||
|
||||
public openSelect(event: boolean): void {
|
||||
if (event) {
|
||||
this.cdkVirtualScrollViewPort.scrollToIndex(0);
|
||||
this.cdkVirtualScrollViewPort.checkViewportSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get a list filtered by the entered search value.
|
||||
*
|
||||
@ -167,15 +182,30 @@ export class SearchValueSelectorComponent extends BaseFormControlComponentDirect
|
||||
}
|
||||
}
|
||||
|
||||
public removeItem(itemId: number): void {
|
||||
const items = <number[]>this.contentForm.value;
|
||||
items.splice(
|
||||
items.findIndex(item => item === itemId),
|
||||
1
|
||||
);
|
||||
this.contentForm.setValue(items);
|
||||
public removeChipItem(item: Selectable): void {
|
||||
this.addRemoveId(item.id);
|
||||
}
|
||||
|
||||
private addRemoveId(item: number): void {
|
||||
const idx = this.selectedIds.indexOf(item);
|
||||
if (idx > -1) {
|
||||
this.selectedIds.splice(idx, 1);
|
||||
} else {
|
||||
this.selectedIds.push(item);
|
||||
}
|
||||
this.contentForm.setValue(this.selectedIds);
|
||||
}
|
||||
|
||||
public onSelectionChange(change: MatOptionSelectionChange): void {
|
||||
if (change.isUserInput) {
|
||||
const value = change.source.value;
|
||||
this.addRemoveId(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Satisfy parent
|
||||
*/
|
||||
public onContainerClick(event: MouseEvent): void {
|
||||
if ((event.target as Element).tagName.toLowerCase() !== 'select') {
|
||||
// this.element.nativeElement.querySelector('select').focus();
|
||||
@ -197,5 +227,16 @@ export class SearchValueSelectorComponent extends BaseFormControlComponentDirect
|
||||
|
||||
protected updateForm(value: Selectable[] | null): void {
|
||||
this.contentForm.setValue(value);
|
||||
if (value?.length) {
|
||||
/**
|
||||
* Hack:
|
||||
* for loaded or preselected form, add existing values to selected IDs.
|
||||
* These are usually always numbers,
|
||||
* Would be easier to absolutely always use Selectable and never use IDs,
|
||||
* Could save some work, but every second form has to change for that.
|
||||
* -> os4 todo
|
||||
*/
|
||||
this.selectedIds = value as any;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user