Select

Displays a list of options for the user to pick from—triggered by a button.

PreviousNext
Selected value: apple
import { ChangeDetectionStrategy, Component } from '@angular/core';
 
import { ZardSelectItemComponent } from '../select-item.component';
import { ZardSelectComponent } from '../select.component';
import { ZardBadgeComponent } from '../../badge/badge.component';
 
@Component({
  selector: 'z-demo-select-basic',
  imports: [ZardBadgeComponent, ZardSelectComponent, ZardSelectItemComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="flex flex-col gap-4">
      <span>
        Selected value: <z-badge> {{ selectedValue }} </z-badge>
      </span>
      <z-select class="w-[300px]" zPlaceholder="Selecione uma fruta" [(zValue)]="selectedValue">
        <z-select-item zValue="apple">Apple</z-select-item>
        <z-select-item zValue="banana">Banana</z-select-item>
        <z-select-item zValue="blueberry">Blueberry</z-select-item>
        <z-select-item zValue="grapes">Grapes</z-select-item>
        <z-select-item zValue="pineapple" zDisabled>Pineapple</z-select-item>
      </z-select>
    </div>
  `,
})
export class ZardDemoSelectBasicComponent {
  selectedValue = 'apple';
}
 

Installation

1

Run the CLI

Use the CLI to add the component to your project.

npx @ngzard/ui add select
1

Add the component files

Create the component directory structure and add the following files to your project.

select.component.ts
select.component.ts
import { Overlay, OverlayModule, OverlayPositionBuilder, type OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { CommonModule, isPlatformBrowser } from '@angular/common';
import {
  type AfterContentInit,
  ChangeDetectionStrategy,
  Component,
  computed,
  contentChildren,
  ElementRef,
  forwardRef,
  inject,
  input,
  model,
  type OnDestroy,
  output,
  PLATFORM_ID,
  signal,
  type TemplateRef,
  viewChild,
  ViewContainerRef,
} from '@angular/core';
import { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
 
import type { ClassValue } from 'clsx';
 
import { ZardSelectItemComponent } from './select-item.component';
import { selectContentVariants, selectTriggerVariants, selectVariants, type ZardSelectTriggerVariants } from './select.variants';
import { isElementContentTruncated, mergeClasses, transform } from '../../shared/utils/utils';
import { ZardBadgeComponent } from '../badge/badge.component';
import { ZardIconComponent } from '../icon/icon.component';
 
type OnTouchedType = () => void;
type OnChangeType = (value: string) => void;
 
@Component({
  selector: 'z-select, [z-select]',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, OverlayModule, ZardBadgeComponent, ZardIconComponent],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ZardSelectComponent),
      multi: true,
    },
  ],
  host: {
    '[attr.data-disabled]': 'zDisabled() ? "" : null',
    '[attr.data-state]': 'isOpen() ? "open" : "closed"',
    '[class]': 'classes()',
    '(document:click)': 'onDocumentClick($event)',
  },
  template: `
    <button
      type="button"
      [class]="triggerClasses()"
      [disabled]="zDisabled()"
      (click)="toggle()"
      (keydown)="onTriggerKeydown($event)"
      [attr.aria-expanded]="isOpen()"
      [attr.aria-haspopup]="'listbox'"
      [attr.data-state]="isOpen() ? 'open' : 'closed'"
      [attr.data-placeholder]="!zValue() ? '' : null"
    >
      <span class="flex flex-1 flex-wrap items-center gap-2">
        @let labels = selectedLabels();
        @for (label of labels; track index; let index = $index) {
          <ng-container *ngTemplateOutlet="labelsTemplate; context: { $implicit: label }"> </ng-container>
        } @empty {
          <span class="text-muted-foreground truncate">{{ zPlaceholder() }}</span>
        }
      </span>
      <z-icon zType="chevron-down" zSize="lg" class="opacity-50" />
    </button>
 
    <ng-template #labelsTemplate let-label>
      @if (zMultiple()) {
        <z-badge zType="secondary">
          <span class="truncate">{{ label }}</span>
        </z-badge>
      } @else {
        <span class="truncate">{{ label }}</span>
      }
    </ng-template>
 
    <ng-template #dropdownTemplate>
      <div [class]="contentClasses()" role="listbox" [attr.data-state]="'open'" (keydown)="onDropdownKeydown($event)" tabindex="-1">
        <div class="p-1">
          <ng-content></ng-content>
        </div>
      </div>
    </ng-template>
  `,
})
export class ZardSelectComponent implements ControlValueAccessor, AfterContentInit, OnDestroy {
  private readonly elementRef = inject(ElementRef);
  private readonly overlay = inject(Overlay);
  private readonly overlayPositionBuilder = inject(OverlayPositionBuilder);
  private readonly viewContainerRef = inject(ViewContainerRef);
  private readonly platformId = inject(PLATFORM_ID);
 
  readonly dropdownTemplate = viewChild.required<TemplateRef<void>>('dropdownTemplate');
  protected readonly selectItems = contentChildren(ZardSelectItemComponent);
 
  private overlayRef?: OverlayRef;
  private portal?: TemplatePortal;
 
  readonly class = input<ClassValue>('');
  readonly zDisabled = input(false, { transform });
  readonly zLabel = input<string>('');
  readonly zMaxLabelCount = input<number>(1);
  readonly zMultiple = input<boolean>(false);
  readonly zPlaceholder = input<string>('Select an option...');
  readonly zSize = input<ZardSelectTriggerVariants['zSize']>('default');
  readonly zValue = model<string | string[]>(this.zMultiple() ? [] : '');
 
  readonly zSelectionChange = output<string | string[]>();
 
  readonly isOpen = signal(false);
  readonly focusedIndex = signal<number>(-1);
 
  // Compute the label based on selected value
  readonly selectedLabels = computed<string[]>(() => {
    const selectedValue = this.zValue();
    if (this.zMultiple() && Array.isArray(selectedValue)) {
      return this.provideLabelsForMultiselectMode(selectedValue);
    }
 
    return this.provideLabelForSingleSelectMode(selectedValue as string);
  });
 
  private onChange: OnChangeType = (_value: string) => {
    // ControlValueAccessor onChange callback
  };
 
  private onTouched: OnTouchedType = () => {
    // ControlValueAccessor onTouched callback
  };
 
  protected readonly classes = computed(() => mergeClasses(selectVariants(), this.class()));
  protected readonly contentClasses = computed(() => mergeClasses(selectContentVariants()));
  protected readonly triggerClasses = computed(() =>
    mergeClasses(
      selectTriggerVariants({
        zSize: this.zSize(),
      }),
      this.class(),
    ),
  );
 
  ngAfterContentInit() {
    // Setup select host reference for each item
    for (const item of this.selectItems()) {
      item.setSelectHost({
        selectedValue: () => (this.zMultiple() ? (this.zValue() as string[]) : [this.zValue() as string]),
        selectItem: (value: string, label: string) => this.selectItem(value, label),
      });
    }
  }
 
  ngOnDestroy() {
    this.destroyOverlay();
  }
 
  onDocumentClick(event: Event) {
    const target = event.target as Node;
    const clickedInside = this.elementRef.nativeElement.contains(target);
    const clickedInOverlay = this.overlayRef?.overlayElement?.contains(target);
 
    if (!clickedInside && !clickedInOverlay) {
      this.close();
    }
  }
 
  onTriggerKeydown(event: KeyboardEvent) {
    switch (event.key) {
      case 'Enter':
      case ' ':
      case 'ArrowDown':
      case 'ArrowUp':
        event.preventDefault();
        if (!this.isOpen()) {
          this.open();
        }
        break;
      case 'Escape':
        if (this.isOpen()) {
          event.preventDefault();
          this.close();
        }
        break;
    }
  }
 
  onDropdownKeydown(event: KeyboardEvent) {
    const items = this.getSelectItems();
 
    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        this.navigateItems(1, items);
        break;
      case 'ArrowUp':
        event.preventDefault();
        this.navigateItems(-1, items);
        break;
      case 'Enter':
      case ' ':
        event.preventDefault();
        this.selectFocusedItem(items);
        break;
      case 'Escape':
        event.preventDefault();
        this.close();
        this.focusButton();
        break;
      case 'Home':
        event.preventDefault();
        this.focusFirstItem(items);
        break;
      case 'End':
        event.preventDefault();
        this.focusLastItem(items);
        break;
    }
  }
 
  toggle() {
    if (this.zDisabled()) return;
 
    if (this.isOpen()) {
      this.close();
    } else {
      this.open();
    }
  }
 
  selectItem(value: string, label: string) {
    if (value === undefined || value === null || value === '') {
      console.warn('Attempted to select item with invalid value:', { value, label });
      return;
    }
 
    this.zValue.update(selectedValues => {
      if (Array.isArray(selectedValues)) {
        return selectedValues.includes(value) ? selectedValues.filter(v => v !== value) : [...selectedValues, value];
      }
 
      return value;
    });
    this.onChange(value);
    this.zSelectionChange.emit(this.zValue());
 
    if (!this.zMultiple()) {
      this.close();
 
      // Return focus to the button after selection
      setTimeout(() => {
        this.focusButton();
      }, 0);
    }
  }
 
  private provideLabelsForMultiselectMode(selectedValue: string[]): string[] {
    const labelsToShowCount = selectedValue.length - this.zMaxLabelCount();
    const labels = [];
    let index = 0;
    for (const value of selectedValue) {
      const matchingItem = this.getMatchingItem(value);
      if (matchingItem) {
        labels.push(matchingItem.label());
        index++;
      }
      if (labelsToShowCount && this.zMaxLabelCount() && index === this.zMaxLabelCount()) {
        labels.push(`${labelsToShowCount} more item${labelsToShowCount > 1 ? 's' : ''} selected`);
        break;
      }
    }
    return labels;
  }
 
  private provideLabelForSingleSelectMode(selectedValue: string): string[] {
    const manualLabel = this.zLabel();
    if (manualLabel) return [manualLabel];
 
    const matchingItem = this.getMatchingItem(selectedValue);
    if (matchingItem) {
      return [matchingItem.label()];
    }
 
    return selectedValue ? [selectedValue] : [];
  }
 
  private open() {
    if (this.isOpen()) return;
 
    // Create overlay if it doesn't exist
    if (!this.overlayRef) {
      this.createOverlay();
    }
 
    if (!this.overlayRef) return;
 
    const hostWidth = this.elementRef.nativeElement.offsetWidth || 0;
 
    if (this.overlayRef.hasAttached()) {
      this.overlayRef.detach();
    }
 
    this.portal = new TemplatePortal(this.dropdownTemplate(), this.viewContainerRef);
 
    this.overlayRef.attach(this.portal);
    this.overlayRef.updateSize({ width: hostWidth });
    this.isOpen.set(true);
 
    this.determinePortalWidth(hostWidth);
 
    // Focus dropdown after opening and position on selected item
    setTimeout(() => {
      this.focusDropdown();
      this.focusSelectedItem();
    }, 0);
  }
 
  private close() {
    if (this.overlayRef?.hasAttached()) {
      this.overlayRef.detach();
    }
    this.isOpen.set(false);
    this.focusedIndex.set(-1);
    this.onTouched();
  }
 
  private getMatchingItem(value: string): ZardSelectItemComponent | undefined {
    return this.selectItems()?.find(item => item.zValue() === value);
  }
 
  private determinePortalWidth(portalWidth: number): void {
    if (!this.overlayRef || !this.overlayRef.hasAttached()) return;
 
    const selectItems = this.selectItems();
    let itemMaxWidth = 0;
    for (const item of selectItems) {
      itemMaxWidth = Math.max(itemMaxWidth, item.elementRef.nativeElement.scrollWidth);
    }
 
    const textContentElement = this.elementRef.nativeElement.querySelector('button > span > span') as HTMLElement;
    const isOverflow = isElementContentTruncated(textContentElement);
 
    if (isOverflow && selectItems.length) {
      const elementStyles = getComputedStyle(selectItems[0].elementRef.nativeElement);
      const leftPadding = Number.parseFloat(elementStyles.getPropertyValue('padding-left')) || 0;
      const rightPadding = Number.parseFloat(elementStyles.getPropertyValue('padding-right')) || 0;
      itemMaxWidth += leftPadding + rightPadding;
    }
 
    itemMaxWidth = Math.max(itemMaxWidth, portalWidth);
    this.overlayRef.updateSize({ width: itemMaxWidth });
    this.overlayRef.updatePosition();
  }
 
  private createOverlay() {
    if (this.overlayRef) return; // Already created
 
    if (isPlatformBrowser(this.platformId)) {
      try {
        const positionStrategy = this.overlayPositionBuilder
          .flexibleConnectedTo(this.elementRef)
          .withPositions([
            {
              originX: 'center',
              originY: 'bottom',
              overlayX: 'center',
              overlayY: 'top',
              offsetY: 4,
            },
            {
              originX: 'center',
              originY: 'top',
              overlayX: 'center',
              overlayY: 'bottom',
              offsetY: -4,
            },
          ])
          .withPush(false);
 
        const elementWidth = this.elementRef.nativeElement.offsetWidth || 200;
 
        this.overlayRef = this.overlay.create({
          positionStrategy,
          hasBackdrop: false,
          scrollStrategy: this.overlay.scrollStrategies.reposition(),
          width: elementWidth,
          maxHeight: 384, // max-h-96 equivalent
        });
      } catch (error) {
        console.error('Error creating overlay:', error);
      }
    }
  }
 
  private destroyOverlay() {
    if (this.overlayRef) {
      this.overlayRef.dispose();
      this.overlayRef = undefined;
    }
  }
 
  private getSelectItems(): HTMLElement[] {
    if (!this.overlayRef?.hasAttached()) return [];
    const dropdownElement = this.overlayRef.overlayElement;
    return Array.from(dropdownElement.querySelectorAll<HTMLElement>('z-select-item, [z-select-item]')).filter(item => item.dataset['disabled'] === undefined);
  }
 
  private navigateItems(direction: number, items: HTMLElement[]) {
    if (items.length === 0) return;
 
    const currentIndex = this.focusedIndex();
    let nextIndex = currentIndex + direction;
 
    if (nextIndex < 0) {
      nextIndex = items.length - 1;
    } else if (nextIndex >= items.length) {
      nextIndex = 0;
    }
 
    this.focusedIndex.set(nextIndex);
    this.updateItemFocus(items, nextIndex);
  }
 
  private selectFocusedItem(items: HTMLElement[]) {
    const currentIndex = this.focusedIndex();
    if (currentIndex >= 0 && currentIndex < items.length) {
      const item = items[currentIndex];
      const value = item.getAttribute('value');
      const label = item.textContent?.trim() ?? '';
 
      if (value === null || value === undefined) {
        console.warn('No value attribute found on selected item:', item);
        return;
      }
 
      this.selectItem(value, label);
    }
  }
 
  private focusFirstItem(items: HTMLElement[]) {
    if (items.length > 0) {
      this.focusedIndex.set(0);
      this.updateItemFocus(items, 0);
    }
  }
 
  private focusLastItem(items: HTMLElement[]) {
    if (items.length > 0) {
      const lastIndex = items.length - 1;
      this.focusedIndex.set(lastIndex);
      this.updateItemFocus(items, lastIndex);
    }
  }
 
  private updateItemFocus(items: HTMLElement[], focusedIndex: number) {
    for (let index = 0; index < items.length; index++) {
      const item = items[index];
      if (index === focusedIndex) {
        item.focus();
        item.setAttribute('aria-selected', 'true');
      } else {
        item.removeAttribute('aria-selected');
      }
    }
  }
 
  private focusDropdown() {
    if (this.overlayRef?.hasAttached()) {
      const dropdownElement = this.overlayRef.overlayElement.querySelector('[role="listbox"]') as HTMLElement;
      if (dropdownElement) {
        dropdownElement.focus();
      }
    }
  }
 
  private focusButton() {
    const button = this.elementRef.nativeElement.querySelector('button');
    if (button) {
      button.focus();
    }
  }
 
  private focusSelectedItem() {
    const items = this.getSelectItems();
    if (items.length === 0) return;
 
    // Find the index of the currently selected item
    const selectedValue = this.zValue();
    let selectedIndex = -1;
 
    if (selectedValue) {
      selectedIndex = items.findIndex(item => item.getAttribute('value') === selectedValue);
    }
 
    // If no item is selected, focus the first item
    if (selectedIndex === -1) {
      selectedIndex = 0;
    }
 
    this.focusedIndex.set(selectedIndex);
    this.updateItemFocus(items, selectedIndex);
  }
 
  // ControlValueAccessor implementation
  writeValue(value: string | string[] | null): void {
    if (this.zMultiple() && Array.isArray(value)) {
      this.zValue.set(value);
    } else {
      this.zValue.set(value ?? '');
    }
  }
 
  registerOnChange(fn: (value: string) => void): void {
    this.onChange = fn;
  }
 
  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }
 
  setDisabledState(): void {
    // The disabled state is handled by the disabled input
  }
}
 
select.variants.ts
select.variants.ts
import { cva, type VariantProps } from 'class-variance-authority';
 
export const selectVariants = cva('relative inline-block w-full');
 
export const selectTriggerVariants = cva(
  'flex w-full justify-between gap-2 rounded-md border border-input bg-transparent px-3 shadow-xs transition-[color,box-shadow] outline-none cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 data-placeholder:text-muted-foreground [&_svg:not([class*="text-"])]:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*="size-"])]:size-4',
  {
    variants: {
      zSize: {
        sm: 'min-h-8 py-1 text-xs',
        default: 'min-h-9 py-1.5 text-sm',
        lg: 'min-h-10 py-2 text-base',
      },
    },
    defaultVariants: {
      zSize: 'default',
    },
  },
);
export const selectContentVariants = cva('z-9999 min-w-full overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-lg animate-in fade-in-0 zoom-in-95');
export const selectItemVariants = cva(
  'relative flex min-w-full cursor-pointer text-nowrap items-center gap-2 rounded-sm mb-0.5 py-1.5 pr-8 pl-2 text-sm outline-hidden select-none hover:bg-accent hover:text-accent-foreground data-selected:bg-accent data-selected:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-disabled:cursor-not-allowed data-disabled:hover:bg-transparent data-disabled:hover:text-current [&_svg:not([class*="text-"])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*="size-"])]:size-4',
);
 
export type ZardSelectTriggerVariants = VariantProps<typeof selectTriggerVariants>;
export type ZardSelectContentVariants = VariantProps<typeof selectContentVariants>;
export type ZardSelectItemVariants = VariantProps<typeof selectItemVariants>;
 
select-item.component.ts
select-item.component.ts
import { ChangeDetectionStrategy, Component, computed, ElementRef, inject, input, linkedSignal, signal } from '@angular/core';
 
import { selectItemVariants } from './select.variants';
import { mergeClasses, transform } from '../../shared/utils/utils';
import { ZardIconComponent } from '../icon/icon.component';
 
// Interface to avoid circular dependency
interface SelectHost {
  selectedValue(): string[];
  selectItem(value: string, label: string): void;
}
 
@Component({
  selector: 'z-select-item, [z-select-item]',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [ZardIconComponent],
  host: {
    '[class]': 'classes()',
    '[attr.value]': 'zValue()',
    role: 'option',
    tabindex: '-1',
    '[attr.data-disabled]': 'zDisabled() ? "" : null',
    '[attr.data-selected]': 'isSelected() ? "" : null',
    '[attr.aria-selected]': 'isSelected()',
    '(click)': 'onClick()',
  },
  template: `
    @if (isSelected()) {
      <span class="absolute right-2 flex size-3.5 items-center justify-center">
        <z-icon zType="check" />
      </span>
    }
    <span class="truncate">
      <ng-content></ng-content>
    </span>
  `,
})
export class ZardSelectItemComponent {
  readonly zValue = input.required<string>();
  readonly zDisabled = input(false, { transform });
  readonly class = input<string>('');
 
  private readonly select = signal<SelectHost | null>(null);
  readonly elementRef = inject(ElementRef);
  readonly label = linkedSignal<string>(() => {
    const element = this.elementRef?.nativeElement;
    return (element?.textContent ?? element?.innerText)?.trim() ?? '';
  });
 
  protected readonly classes = computed(() => mergeClasses(selectItemVariants(), this.class()));
  protected readonly isSelected = computed(() => this.select()?.selectedValue().includes(this.zValue()));
 
  setSelectHost(selectHost: SelectHost) {
    this.select.set(selectHost);
  }
 
  onClick() {
    if (this.zDisabled()) return;
    this.select()?.selectItem(this.zValue(), this.label());
  }
}
 

Examples

default

Selected value: apple
import { ChangeDetectionStrategy, Component } from '@angular/core';
 
import { ZardSelectItemComponent } from '../select-item.component';
import { ZardSelectComponent } from '../select.component';
import { ZardBadgeComponent } from '../../badge/badge.component';
 
@Component({
  selector: 'z-demo-select-basic',
  imports: [ZardBadgeComponent, ZardSelectComponent, ZardSelectItemComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="flex flex-col gap-4">
      <span>
        Selected value: <z-badge> {{ selectedValue }} </z-badge>
      </span>
      <z-select class="w-[300px]" zPlaceholder="Selecione uma fruta" [(zValue)]="selectedValue">
        <z-select-item zValue="apple">Apple</z-select-item>
        <z-select-item zValue="banana">Banana</z-select-item>
        <z-select-item zValue="blueberry">Blueberry</z-select-item>
        <z-select-item zValue="grapes">Grapes</z-select-item>
        <z-select-item zValue="pineapple" zDisabled>Pineapple</z-select-item>
      </z-select>
    </div>
  `,
})
export class ZardDemoSelectBasicComponent {
  selectedValue = 'apple';
}
 

multi select

import { ChangeDetectionStrategy, Component, effect, signal } from '@angular/core';
 
import { ZardSelectItemComponent } from '../select-item.component';
import { ZardSelectComponent } from '../select.component';
 
@Component({
  selector: 'z-demo-multi-select-basic',
  imports: [ZardSelectComponent, ZardSelectItemComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <z-select
      zPlaceholder="Select multiple fruits"
      [zMultiple]="true"
      [zMaxLabelCount]="4"
      [(zValue)]="selectedValues"
      class="w-[300px]"
    >
      <z-select-item zValue="apple">Apple</z-select-item>
      <z-select-item zValue="banana">Banana</z-select-item>
      <z-select-item zValue="blueberry">Blueberry</z-select-item>
      <z-select-item zValue="grapes">Grapes</z-select-item>
      <z-select-item zValue="pineapple">Pineapple</z-select-item>
      <z-select-item zValue="strawberry">Strawberry</z-select-item>
      <z-select-item zValue="watermelon">Watermelon</z-select-item>
      <z-select-item zValue="kiwi">Kiwi</z-select-item>
      <z-select-item zValue="mango">Mango</z-select-item>
    </z-select>
  `,
})
export class ZardDemoMultiSelectBasicComponent {
  selectedValues = signal<string[]>([]);
 
  constructor() {
    effect(() => {
      console.log(this.selectedValues());
    });
  }
}
 

API

z-select

A customizable select component that allows single value selection.

Input Description Type Default
[class] Custom CSS classes string ''
[zDisabled] Disables the select boolean false
[zLabel] Optional label for the select string ''
[zMaxLabelCount] Limits visible labels in multiselect mode number 1
[zMultiple] Multiselect mode boolean false
[zPlaceholder] Placeholder text string 'Select an option...'
[(zValue)] Selected value string | string[] '' | []
Output Description Payload
(zSelectionChange) Emitted when the selected value changes string | string[]

z-select-item

Represents an individual item inside a z-select component.

Input Description Type Default
[class] Custom CSS classes string ''
[zValue] The value associated with this item string ''
[zDisabled] Disables selection for this item boolean false