@progress/kendo-angular-dropdowns
Version:
A wide variety of native Angular dropdown components including AutoComplete, ComboBox, DropDownList, DropDownTree, MultiColumnComboBox, MultiSelect, and MultiSelectTree
785 lines (784 loc) • 34.1 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Component, Input, Output, EventEmitter, ViewChildren, QueryList, ElementRef, ViewChild, ChangeDetectorRef, NgZone, Renderer2 } from '@angular/core';
import { ResizeSensorComponent, TemplateContextDirective, isChanged } from '@progress/kendo-angular-common';
import { ListItemDirective } from './list-item.directive';
import { ItemTemplateDirective } from './templates/item-template.directive';
import { GroupTemplateDirective } from './templates/group-template.directive';
import { FixedGroupTemplateDirective } from './templates/fixed-group-template.directive';
import { isPresent, getter, closest, getSizeClass, getRoundedClass } from './util';
import { SelectionService } from './selection/selection.service';
import { fromEvent, merge } from 'rxjs';
import { map, tap, auditTime, switchMap, take } from 'rxjs/operators';
import { DisabledItemsService } from './disabled-items/disabled-items.service';
import { DataService } from './data.service';
import { NavigationAction } from './navigation/navigation-action';
import { SelectableDirective } from './selection/selectable.directive';
import { NgIf, NgStyle, NgFor, NgClass } from '@angular/common';
import * as i0 from "@angular/core";
import * as i1 from "./data.service";
import * as i2 from "./selection/selection.service";
import * as i3 from "./disabled-items/disabled-items.service";
/**
* @hidden
*/
export class ListComponent {
dataService;
wrapper;
selectionService;
disabledItemsService;
cdr;
zone;
renderer;
selected = [];
focused = -1;
textField;
valueField;
height;
template;
groupTemplate;
fixedGroupTemplate;
show = true;
id;
optionPrefix;
multipleSelection = false;
virtual;
type = 'list';
checkboxes = { enabled: false };
ariaLive;
isMultiselect;
isActionSheetExpanded;
showStickyHeader;
rowWidth;
set data(data) {
this._data = data[0] && data[0].header ? data.slice(0) : data;
}
get data() {
return this._data;
}
set size(size) {
if (this.type === 'list') {
this.renderer.removeClass(this.wrapper.nativeElement, getSizeClass('list', this.size));
if (size) {
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('list', size));
}
this._size = size;
}
}
get size() {
return this._size;
}
rounded = 'medium';
onClick = new EventEmitter();
pageChange = new EventEmitter();
listResize = new EventEmitter();
popupListScroll = new EventEmitter();
items;
content;
list;
virtualContainer;
currentGroup;
startFrom = 0;
lastLoaded = 0;
lastScrollTop = 0;
listContentClass;
listClass;
listItemClass;
listVirtualClass;
listGroupStickyHeaderClass;
listGroupStickyHeaderTextClass;
listGroupItemClass;
listGroupItemTextClass;
scrollToFocused = false;
_data;
scrollSubscription;
selectSubscription;
_size = 'medium';
get pageSize() {
if (this.virtual.pageSize) {
return this.virtual.pageSize;
}
const size = Math.round(this.height / this.virtual.itemHeight);
return size;
}
get scrollHeight() {
return this.virtual.total * this.virtual.itemHeight;
}
get overflowY() {
if (isPresent(this.virtual)) {
const overflow = this.hasVirtualScrollbar() ? 'scroll' : 'hidden';
return overflow;
}
}
/**
* @hidden
*/
get checkboxClasses() {
return `${this.size ? getSizeClass('checkbox', this.size) : ''} ${this.rounded ? getRoundedClass(this.rounded) : ''}`;
}
/* tslint:disable:member-ordering */
constructor(dataService, wrapper, selectionService, disabledItemsService, cdr, zone, renderer) {
this.dataService = dataService;
this.wrapper = wrapper;
this.selectionService = selectionService;
this.disabledItemsService = disabledItemsService;
this.cdr = cdr;
this.zone = zone;
this.renderer = renderer;
this.selectSubscription = merge(this.selectionService.onSelect.pipe(map((args) => args.indices[0])), this.selectionService.onFocus)
.pipe(
// handle only the very last onSelect/onFocus emission
switchMap(event => this.zone.onStable.pipe(take(1), map(() => event))))
.subscribe(this.scrollToItem.bind(this));
this.prepareClasses();
}
ngOnChanges(changes) {
if (isChanged('data', changes, false)) {
if (this.lastLoaded <= 0) {
this.lastLoaded = this.data.length - 1;
this.scrollToFocused = !changes['data'].isFirstChange();
}
this.setOverflow();
this.zone.onStable.pipe(take(1)).subscribe(() => {
this.setGroupAttributes();
});
}
if (isChanged('virtual', changes, false)) {
this.setOverflow();
}
if (isChanged('type', changes, false)) {
this.prepareClasses();
}
}
ngAfterViewInit() {
this.setComponentClasses();
this.zone.runOutsideAngular(() => {
this.scrollSubscription = fromEvent(this.content.nativeElement, "scroll").pipe(auditTime(100), tap(this.prefetchData.bind(this)), tap(this.findCurrentGroup.bind(this))).subscribe(() => {
this.lastScrollTop = this.content.nativeElement.scrollTop;
});
});
this.setGroupAttributes();
this.setOverflow();
}
setGroupAttributes() {
const liItems = document.querySelectorAll('li');
let isGroup;
let childrenliItemsIds = [];
let firstGroupReached = false;
let previousGroup;
liItems.forEach((li, idx) => {
isGroup = li.getAttribute('role') === 'group';
if (!isGroup && firstGroupReached) {
this.renderer.setAttribute(li, 'aria-describedby', previousGroup.getAttribute('id'));
childrenliItemsIds.push(li.getAttribute('id'));
if (idx + 1 >= liItems.length || liItems[idx + 1]?.getAttribute('role') === 'group') {
this.renderer.setAttribute(previousGroup, 'aria-owns', childrenliItemsIds.join(' '));
childrenliItemsIds = [];
}
}
if (isGroup) {
firstGroupReached = true;
previousGroup = li;
}
});
}
ngAfterViewChecked() {
if (this.virtual) {
this.positionItems();
}
if (this.items && this.scrollToFocused) {
this.scrollToFocused = false;
const scrollTarget = this.items.length && this.selectionService.focused === -1 ? 0 : this.selectionService.focused;
this.scrollToItem(scrollTarget);
}
if (this.dataService.grouped) {
this.findCurrentGroup();
}
}
ngOnDestroy() {
this.selectSubscription.unsubscribe();
if (this.scrollSubscription) {
this.scrollSubscription.unsubscribe();
}
}
onCheckedChange(e, index) {
const isChecked = e.target['checked'];
if (isChecked && !this.selectionService.isSelected(index)) {
this.selectionService.add(index);
}
if (!isChecked && this.selectionService.isSelected(index)) {
this.selectionService.deselect(index);
}
}
prepareClasses() {
if (this.type === 'list') {
this.listContentClass = 'k-list-content';
this.listClass = 'k-list-ul';
this.listItemClass = 'k-list-item';
this.listVirtualClass = 'k-virtual-list';
this.listGroupStickyHeaderClass = 'k-list-group-sticky-header';
this.listGroupStickyHeaderTextClass = 'k-list-header-text';
this.listGroupItemClass = 'k-list-group-item';
this.listGroupItemTextClass = 'k-list-item-text';
}
else {
this.listContentClass = 'k-table-body k-table-scroller';
this.listClass = 'k-table k-table-list';
this.listItemClass = 'k-table-row';
this.listVirtualClass = 'k-virtual-table';
this.listGroupStickyHeaderClass = 'k-table-group-sticky-header';
this.listGroupStickyHeaderTextClass = 'k-table-th';
this.listGroupItemClass = 'k-table-group-row';
this.listGroupItemTextClass = 'k-table-th';
}
}
isChecked(index) {
const normalizedIndex = this.virtual ? index + this.virtual.skip : index;
return this.selectionService.isSelected(normalizedIndex);
}
firstVisibleItem() {
const content = this.content.nativeElement;
const rect = content.getBoundingClientRect();
// IE9 hack
const disabled = Array.prototype.slice.call(content.querySelectorAll(".k-disabled"));
// This is a workaround for finding elements with pointer-events: none;
disabled.forEach((el) => this.renderer.setStyle(el, "pointer-events", "auto"));
const item = document.elementFromPoint(rect.left + 1, rect.top + 1);
disabled.forEach((el) => this.renderer.setStyle(el, "pointer-events", "none"));
// return the closest `li` item to cover the custom template scenario
return closest(item, 'li');
}
findCurrentGroup() {
if (!this.dataService.grouped) {
this.currentGroup = undefined;
return;
}
const item = this.firstVisibleItem();
if (item) {
let index;
if (item.getAttribute("role") === "group") {
index = parseInt(item.getAttribute("group-index"), 10);
this.currentGroup = this.dataService.groupAt(index)?.value;
}
else {
index = parseInt(item.getAttribute("index"), 10);
this.currentGroup = this.dataService.itemGroup(this.dataService.itemAt(index));
}
}
else {
this.currentGroup = undefined;
}
this.cdr.detectChanges();
}
prefetchData() {
if (!this.virtual) {
return;
}
const visibleItems = Math.trunc(this.content.nativeElement.clientHeight / this.virtual.itemHeight);
const offsetY = this.content.nativeElement.scrollTop;
const start = Math.trunc(offsetY / this.virtual.itemHeight);
const down = offsetY > this.lastScrollTop;
const nextPage = (start + visibleItems >= this.lastLoaded) && this.lastLoaded < this.virtual.total - 1;
const leftOver = this.pageSize - (this.lastLoaded - this.startFrom);
const prevPage = this.lastLoaded - this.pageSize + visibleItems >= start - leftOver;
if (down && nextPage) {
this.changePage(start);
}
if (!down && prevPage) {
this.changePage(start - this.pageSize + visibleItems + 1);
}
}
changePage(start) {
this.zone.run(() => {
let end = this.pageSize + start;
if (end > this.virtual.total) {
start--;
end = this.virtual.total;
}
if (start < 0) {
start = 0;
}
this.startFrom = start;
this.lastLoaded = end;
this.pageChange.emit({ skip: start, take: this.pageSize });
});
this.setGroupAttributes();
}
index(groupIndex, itemIndex) {
return groupIndex > 0 ? (this.dataService.groupIndices[groupIndex - 1] + itemIndex) : itemIndex;
}
getText(dataItem) {
return getter(dataItem, this.textField);
}
getValue(dataItem) {
return getter(dataItem, this.valueField);
}
isDisabled(index) {
if (isPresent(this.virtual) && !this.dataService.grouped) {
index += this.virtual.skip;
}
return this.disabledItemsService.isIndexDisabled(index);
}
isAltRow(index) {
return this.type === 'dropdowngrid' && index % 2 !== 0;
}
scrollToItem(index) {
let flatIndex = index;
if (this.dataService.grouped) {
// takes into account the group header items
flatIndex = this.dataService.flatIndex(index);
}
if (this.virtual && flatIndex > -1) {
this.scrollToIndex(flatIndex);
return;
}
const items = this.items.toArray();
if (isPresent(items[flatIndex]) && flatIndex !== -1) {
this.scroll(items[flatIndex].element);
}
}
scrollWithOnePage(action) {
const content = this.content.nativeElement;
const contentOffsetHeight = content.clientHeight;
if (action === NavigationAction.PageDown) {
content.scrollTop += contentOffsetHeight;
}
else if (action === NavigationAction.PageUp) {
content.scrollTop -= contentOffsetHeight;
}
}
scrollToIndex(index) {
const content = this.content.nativeElement;
let contentScrollTop = content.scrollTop;
const itemOffsetTop = index * this.virtual.itemHeight;
const itemOffsetHeight = this.virtual.itemHeight;
const contentOffsetHeight = content.clientHeight;
const bottomDistance = itemOffsetTop + itemOffsetHeight;
if (contentScrollTop > itemOffsetTop) {
contentScrollTop = itemOffsetTop;
}
else if (bottomDistance > (contentScrollTop + contentOffsetHeight)) {
contentScrollTop = (bottomDistance - contentOffsetHeight);
}
content.scrollTop = contentScrollTop;
}
scroll(item) {
if (!item) {
return;
}
const nativeElement = item.nativeElement;
const content = this.content.nativeElement;
const itemOffsetTop = nativeElement.offsetTop;
const itemOffsetHeight = nativeElement.offsetHeight;
let contentScrollTop = content.scrollTop;
const contentOffsetHeight = content.clientHeight;
const bottomDistance = itemOffsetTop + itemOffsetHeight;
if (contentScrollTop > itemOffsetTop) {
contentScrollTop = itemOffsetTop;
}
else if (bottomDistance > (contentScrollTop + contentOffsetHeight)) {
contentScrollTop = (bottomDistance - contentOffsetHeight);
}
content.scrollTop = contentScrollTop;
}
/**
* Indicates whether a scrollbar is currently rendered in the list.
*/
hasScrollbar() {
if (!(isPresent(this.items) && this.items.length && isPresent(this.list) && isPresent(this.content))) {
return false;
}
const hasVirtualScroll = isPresent(this.virtual) && this.hasVirtualScrollbar();
return hasVirtualScroll || this.list.nativeElement.scrollHeight > this.content.nativeElement.offsetHeight;
}
isItemSelected(index) {
return this.selectionService.isSelected(index) || null;
}
/**
* Sets the list's content overflow (hides/shows scrollbar)
*/
setOverflow() {
if (this.virtual) {
const overflow = this.hasVirtualScrollbar() ? 'scroll' : 'hidden';
this.renderer.setStyle(this.content.nativeElement, 'overflow-y', overflow);
}
}
/**
* Indicates whether the scrollbar should be visible in virtual mode.
*/
hasVirtualScrollbar() {
const contentOffsetHeight = this.content.nativeElement.offsetHeight;
const virtualOffsetHeight = this.virtualContainer && this.virtualContainer.nativeElement.offsetHeight;
return this.virtualContainer && virtualOffsetHeight > contentOffsetHeight;
}
positionItems() {
this.items.forEach((item, index) => {
const offsetY = (index + this.startFrom) * this.virtual.itemHeight;
this.renderer.setStyle(item.element.nativeElement, "transform", `translateY(${offsetY}px`);
});
}
/**
* Indicates whether the first group header from the data set is in the targeted virtual page.
*/
firstGroupHeaderInTargetedPage(itemIndex) {
if (!isPresent(this.virtual)) {
return true;
}
return this.virtual.skip === 0 && (this.virtual.pageSize > itemIndex);
}
setComponentClasses() {
if (this.type === 'list') {
this.renderer.addClass(this.wrapper.nativeElement, 'k-list');
if (this.size) {
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('list', this.size));
}
}
if (this.type === 'dropdowngrid') {
this.renderer.setStyle(this.wrapper.nativeElement, 'overflow-y', 'scroll');
}
if (isPresent(this.virtual)) {
this.renderer.addClass(this.wrapper.nativeElement, this.listVirtualClass);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ListComponent, deps: [{ token: i1.DataService }, { token: i0.ElementRef }, { token: i2.SelectionService }, { token: i3.DisabledItemsService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ListComponent, isStandalone: true, selector: "kendo-list", inputs: { selected: "selected", focused: "focused", textField: "textField", valueField: "valueField", height: "height", template: "template", groupTemplate: "groupTemplate", fixedGroupTemplate: "fixedGroupTemplate", show: "show", id: "id", optionPrefix: "optionPrefix", multipleSelection: "multipleSelection", virtual: "virtual", type: "type", checkboxes: "checkboxes", ariaLive: "ariaLive", isMultiselect: "isMultiselect", isActionSheetExpanded: "isActionSheetExpanded", showStickyHeader: "showStickyHeader", rowWidth: "rowWidth", data: "data", size: "size", rounded: "rounded" }, outputs: { onClick: "onClick", pageChange: "pageChange", listResize: "listResize", popupListScroll: "popupListScroll" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }, { propertyName: "list", first: true, predicate: ["list"], descendants: true, static: true }, { propertyName: "virtualContainer", first: true, predicate: ["virtualContainer"], descendants: true }, { propertyName: "items", predicate: ListItemDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<div *ngIf="dataService.grouped && showStickyHeader"
[class]="listGroupStickyHeaderClass"
[ngStyle]="{
'height.px': virtual?.itemHeight,
'minHeight.px' : virtual?.itemHeight,
'boxSizing' : virtual ? 'border-box' : 'inherit'}"
>
<ng-template *ngIf="fixedGroupTemplate"
[templateContext]="{
templateRef: fixedGroupTemplate.templateRef,
$implicit: currentGroup
}">
</ng-template>
<ng-template [ngIf]="!fixedGroupTemplate"><span [class]="listGroupStickyHeaderTextClass">{{ currentGroup }}</span></ng-template>
</div>
<div #content
[class]="listContentClass"
[style.maxHeight.px]="height"
unselectable="on"
(scroll)="popupListScroll.emit($event)">
<ul #list
role="listbox"
[class]="listClass"
[attr.id]="id"
[attr.aria-live]="ariaLive"
[attr.aria-multiselectable]="isMultiselect"
[attr.aria-hidden]="!show">
<ng-template *ngIf="!dataService.grouped && show" ngFor let-dataItem let-itemIndex="index" [ngForOf]="data">
<li
role="option"
kendoDropDownsSelectable
[checkboxes]="checkboxes"
[height]="virtual?.itemHeight"
[index]="itemIndex + startFrom"
[multipleSelection]="multipleSelection"
[attr.id]="optionPrefix + '-' + itemIndex"
[attr.tabIndex]="-1"
[attr.aria-selected]="isItemSelected(itemIndex)"
[class]="listItemClass"
[ngClass]="{
'k-disabled': isDisabled(itemIndex),
'k-table-alt-row': isAltRow(itemIndex)
}"
[style.width.px]="rowWidth ?? null"
>
<input
*ngIf="checkboxes.enabled"
type="checkbox"
class="k-checkbox"
role="presentation"
tabindex="-1"
aria-hidden="true"
[ngClass]="checkboxClasses"
(change)="onCheckedChange($event, itemIndex + startFrom)"
[checked]="isChecked(itemIndex)"
/>
<ng-template *ngIf="template"
[templateContext]="{
templateRef: template.templateRef,
$implicit: dataItem
}">
</ng-template>
<ng-template [ngIf]="!template"><span class="k-list-item-text">{{ getText(dataItem) }}</span></ng-template>
</li>
</ng-template>
<ng-template *ngIf="dataService.grouped" ngFor let-dataItem let-itemIndex="index" [ngForOf]="data">
<li
#li
*ngIf="dataItem.header"
role="group"
[class]="listGroupItemClass"
[class.k-table-alt-row]="isAltRow(itemIndex - 1)"
[ngStyle]="{
'height.px': virtual?.itemHeight,
'minHeight.px' : virtual?.itemHeight,
'boxSizing' : virtual ? 'border-box' : 'inherit'}"
[attr.group-index]="dataItem.index"
[attr.id]="optionPrefix + '-' + dataItem.groupIndex + '-' + dataItem.value.toString().split(' ').join('')"
[attr.tabIndex]="-1"
[style.width.px]="rowWidth ?? null">
<span [class]="listGroupItemTextClass">
<ng-template *ngIf="groupTemplate"
[templateContext]="{
templateRef: groupTemplate.templateRef,
$implicit: dataItem.value
}">
</ng-template>
<ng-template [ngIf]="!groupTemplate">{{ dataItem.value }}</ng-template>
</span>
</li>
<li
#li
*ngIf="!dataItem.header"
role="option"
kendoDropDownsSelectable
[height]="virtual?.itemHeight"
[index]="dataItem.offsetIndex"
[multipleSelection]="multipleSelection"
[attr.absolute-index]="dataItem.index"
[attr.id]="optionPrefix + '-' + (itemIndex - 1 - dataItem.groupIndex)"
[attr.tabIndex]="-1"
[attr.aria-selected]="isItemSelected(dataItem.offsetIndex)"
[class]="listItemClass"
[ngClass]="{
'k-disabled': isDisabled(dataItem.offsetIndex),
'k-table-alt-row': isAltRow(itemIndex - 1)
}"
[style.width.px]="rowWidth ?? null"
>
<ng-template *ngIf="template"
[templateContext]="{
templateRef: template.templateRef,
$implicit: dataItem.value
}">
</ng-template>
<ng-template [ngIf]="!template"><span class="k-list-item-text">{{ getText(dataItem.value) }}</span></ng-template>
</li>
</ng-template>
<kendo-resize-sensor
*ngIf="!virtual"
(resize)="listResize.emit()"
>
</kendo-resize-sensor>
</ul>
<div *ngIf="virtual" #virtualContainer class="k-height-container" role="presentation">
<div [style.height.px]="scrollHeight">
<kendo-resize-sensor (resize)="listResize.emit()"></kendo-resize-sensor>
</div>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: ListItemDirective, selector: "\"li[role=option], li[role=group]\"" }, { kind: "directive", type: SelectableDirective, selector: "[kendoDropDownsSelectable]", inputs: ["index", "checkboxes", "height", "isMultiselect", "multipleSelection"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ListComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-list',
template: `
<div *ngIf="dataService.grouped && showStickyHeader"
[class]="listGroupStickyHeaderClass"
[ngStyle]="{
'height.px': virtual?.itemHeight,
'minHeight.px' : virtual?.itemHeight,
'boxSizing' : virtual ? 'border-box' : 'inherit'}"
>
<ng-template *ngIf="fixedGroupTemplate"
[templateContext]="{
templateRef: fixedGroupTemplate.templateRef,
$implicit: currentGroup
}">
</ng-template>
<ng-template [ngIf]="!fixedGroupTemplate"><span [class]="listGroupStickyHeaderTextClass">{{ currentGroup }}</span></ng-template>
</div>
<div #content
[class]="listContentClass"
[style.maxHeight.px]="height"
unselectable="on"
(scroll)="popupListScroll.emit($event)">
<ul #list
role="listbox"
[class]="listClass"
[attr.id]="id"
[attr.aria-live]="ariaLive"
[attr.aria-multiselectable]="isMultiselect"
[attr.aria-hidden]="!show">
<ng-template *ngIf="!dataService.grouped && show" ngFor let-dataItem let-itemIndex="index" [ngForOf]="data">
<li
role="option"
kendoDropDownsSelectable
[checkboxes]="checkboxes"
[height]="virtual?.itemHeight"
[index]="itemIndex + startFrom"
[multipleSelection]="multipleSelection"
[attr.id]="optionPrefix + '-' + itemIndex"
[attr.tabIndex]="-1"
[attr.aria-selected]="isItemSelected(itemIndex)"
[class]="listItemClass"
[ngClass]="{
'k-disabled': isDisabled(itemIndex),
'k-table-alt-row': isAltRow(itemIndex)
}"
[style.width.px]="rowWidth ?? null"
>
<input
*ngIf="checkboxes.enabled"
type="checkbox"
class="k-checkbox"
role="presentation"
tabindex="-1"
aria-hidden="true"
[ngClass]="checkboxClasses"
(change)="onCheckedChange($event, itemIndex + startFrom)"
[checked]="isChecked(itemIndex)"
/>
<ng-template *ngIf="template"
[templateContext]="{
templateRef: template.templateRef,
$implicit: dataItem
}">
</ng-template>
<ng-template [ngIf]="!template"><span class="k-list-item-text">{{ getText(dataItem) }}</span></ng-template>
</li>
</ng-template>
<ng-template *ngIf="dataService.grouped" ngFor let-dataItem let-itemIndex="index" [ngForOf]="data">
<li
#li
*ngIf="dataItem.header"
role="group"
[class]="listGroupItemClass"
[class.k-table-alt-row]="isAltRow(itemIndex - 1)"
[ngStyle]="{
'height.px': virtual?.itemHeight,
'minHeight.px' : virtual?.itemHeight,
'boxSizing' : virtual ? 'border-box' : 'inherit'}"
[attr.group-index]="dataItem.index"
[attr.id]="optionPrefix + '-' + dataItem.groupIndex + '-' + dataItem.value.toString().split(' ').join('')"
[attr.tabIndex]="-1"
[style.width.px]="rowWidth ?? null">
<span [class]="listGroupItemTextClass">
<ng-template *ngIf="groupTemplate"
[templateContext]="{
templateRef: groupTemplate.templateRef,
$implicit: dataItem.value
}">
</ng-template>
<ng-template [ngIf]="!groupTemplate">{{ dataItem.value }}</ng-template>
</span>
</li>
<li
#li
*ngIf="!dataItem.header"
role="option"
kendoDropDownsSelectable
[height]="virtual?.itemHeight"
[index]="dataItem.offsetIndex"
[multipleSelection]="multipleSelection"
[attr.absolute-index]="dataItem.index"
[attr.id]="optionPrefix + '-' + (itemIndex - 1 - dataItem.groupIndex)"
[attr.tabIndex]="-1"
[attr.aria-selected]="isItemSelected(dataItem.offsetIndex)"
[class]="listItemClass"
[ngClass]="{
'k-disabled': isDisabled(dataItem.offsetIndex),
'k-table-alt-row': isAltRow(itemIndex - 1)
}"
[style.width.px]="rowWidth ?? null"
>
<ng-template *ngIf="template"
[templateContext]="{
templateRef: template.templateRef,
$implicit: dataItem.value
}">
</ng-template>
<ng-template [ngIf]="!template"><span class="k-list-item-text">{{ getText(dataItem.value) }}</span></ng-template>
</li>
</ng-template>
<kendo-resize-sensor
*ngIf="!virtual"
(resize)="listResize.emit()"
>
</kendo-resize-sensor>
</ul>
<div *ngIf="virtual" #virtualContainer class="k-height-container" role="presentation">
<div [style.height.px]="scrollHeight">
<kendo-resize-sensor (resize)="listResize.emit()"></kendo-resize-sensor>
</div>
</div>
</div>
`,
standalone: true,
imports: [NgIf, NgStyle, TemplateContextDirective, NgFor, ListItemDirective, SelectableDirective, NgClass, ResizeSensorComponent]
}]
}], ctorParameters: function () { return [{ type: i1.DataService }, { type: i0.ElementRef }, { type: i2.SelectionService }, { type: i3.DisabledItemsService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Renderer2 }]; }, propDecorators: { selected: [{
type: Input
}], focused: [{
type: Input
}], textField: [{
type: Input
}], valueField: [{
type: Input
}], height: [{
type: Input
}], template: [{
type: Input
}], groupTemplate: [{
type: Input
}], fixedGroupTemplate: [{
type: Input
}], show: [{
type: Input
}], id: [{
type: Input
}], optionPrefix: [{
type: Input
}], multipleSelection: [{
type: Input
}], virtual: [{
type: Input
}], type: [{
type: Input
}], checkboxes: [{
type: Input
}], ariaLive: [{
type: Input
}], isMultiselect: [{
type: Input
}], isActionSheetExpanded: [{
type: Input
}], showStickyHeader: [{
type: Input
}], rowWidth: [{
type: Input
}], data: [{
type: Input
}], size: [{
type: Input
}], rounded: [{
type: Input
}], onClick: [{
type: Output
}], pageChange: [{
type: Output
}], listResize: [{
type: Output
}], popupListScroll: [{
type: Output
}], items: [{
type: ViewChildren,
args: [ListItemDirective]
}], content: [{
type: ViewChild,
args: ['content', { static: true }]
}], list: [{
type: ViewChild,
args: ['list', { static: true }]
}], virtualContainer: [{
type: ViewChild,
args: ['virtualContainer', { static: false }]
}] } });