CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ng-select--ng-select

Angular ng-select - All in One UI Select, Multiselect and Autocomplete library providing comprehensive select component functionality

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

template-directives.mddocs/

Template Customization

Angular ng-select provides a comprehensive template directive system allowing complete customization of every visual aspect of the select component. These directives enable developers to create custom layouts, styling, and behavior for options, labels, headers, footers, and various UI states.

Capabilities

Item Display Templates

Template directives for customizing how items and selections are displayed.

/**
 * Template directive for customizing individual option display in dropdown
 * Access to: item, item.label, item.value, item.disabled, index, searchTerm
 */
@Directive({ selector: '[ng-option-tmp]' })
export class NgOptionTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for customizing selected item label display
 * Access to: item, clear function, item.label, item.value
 */
@Directive({ selector: '[ng-label-tmp]' })
export class NgLabelTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for customizing multi-select label display
 * Access to: items array, clear function
 */
@Directive({ selector: '[ng-multi-label-tmp]' })
export class NgMultiLabelTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Directive for displaying and styling item labels with automatic HTML escaping
 * Alternative to using bindLabel property - provides more control over display
 */
@Directive({ selector: '[ngItemLabel]' })
export class NgItemLabelDirective implements OnChanges {
  /** The label text to display */
  @Input() ngItemLabel: string;
  /** Whether to escape HTML in the label (default: true) */
  @Input() escape: boolean = true;

  constructor(private element: ElementRef<HTMLElement>) {}
  
  ngOnChanges(changes: SimpleChanges): void;
}

/**
 * Template directive for customizing option group display
 * Access to: item (group), item.label, item.children
 */
@Directive({ selector: '[ng-optgroup-tmp]' })
export class NgOptgroupTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for customizing tag display when addTag is enabled
 * Access to: searchTerm, item
 */
@Directive({ selector: '[ng-tag-tmp]' })
export class NgTagTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

Usage Examples:

@Component({
  template: `
    <!-- Custom option template with icons and descriptions -->
    <ng-select [(ngModel)]="selectedUser" [clearable]="false">
      <ng-option *ngFor="let user of users" [value]="user">
        <ng-container *ngOptionTemplateDirective="let item=item; let index=index">
          <div class="user-option">
            <img [src]="item.avatar" width="24" height="24" class="avatar">
            <div class="user-info">
              <div class="name">{{ item.name }}</div>
              <div class="email">{{ item.email }}</div>
            </div>
            <span class="role-badge">{{ item.role }}</span>
          </div>
        </ng-container>
      </ng-option>
      
      <!-- Custom selected label template -->
      <ng-label-tmp ng-label-tmp let-item="item" let-clear="clear">
        <img [src]="item.avatar" width="18" height="18">
        {{ item.name }}
        <span class="clear-btn" (click)="clear(item)">×</span>
      </ng-label-tmp>
    </ng-select>
    
    <!-- Multi-select with custom multi-label -->
    <ng-select [(ngModel)]="selectedUsers" [multiple]="true">
      <ng-option *ngFor="let user of users" [value]="user">
        {{ user.name }}
      </ng-option>
      
      <ng-multi-label-tmp ng-multi-label-tmp let-items="items" let-clear="clear">
        <div class="multi-label">
          <span class="selected-count">{{ items.length }} users selected</span>
          <span class="clear-all" (click)="clear()">Clear all</span>
        </div>
      </ng-multi-label-tmp>
    </ng-select>
  `
})
export class CustomTemplatesComponent {
  selectedUser: any;
  selectedUsers: any[] = [];
  users = [
    {
      id: 1, 
      name: 'Alice Johnson', 
      email: 'alice@example.com',
      avatar: '/avatars/alice.jpg',
      role: 'Admin'
    },
    // ... more users
  ];
}

Layout Templates

Template directives for customizing the overall layout and structure of the dropdown.

/**
 * Template directive for dropdown header content
 * Access to: searchTerm, items
 */
@Directive({ selector: '[ng-header-tmp]' })
export class NgHeaderTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for dropdown footer content
 * Access to: searchTerm, items
 */
@Directive({ selector: '[ng-footer-tmp]' })
export class NgFooterTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

Usage Examples:

@Component({
  template: `
    <ng-select [(ngModel)]="selectedItem" [items]="items" bindLabel="name">
      <!-- Custom header with search stats -->
      <ng-header-tmp>
        <div class="dropdown-header">
          <h4>Select an Item</h4>
          <small *ngIf="searchTerm">
            Showing results for "{{ searchTerm }}"
          </small>
        </div>
      </ng-header-tmp>
      
      <!-- Custom footer with action buttons -->
      <ng-footer-tmp>
        <div class="dropdown-footer">
          <button type="button" (click)="addNewItem()">Add New Item</button>
          <button type="button" (click)="selectAll()">Select All</button>
        </div>
      </ng-footer-tmp>
    </ng-select>
  `
})
export class HeaderFooterComponent {
  selectedItem: any;
  searchTerm: string = '';
  items = [/* ... */];
  
  addNewItem() {
    // Custom logic to add new item
  }
  
  selectAll() {
    // Custom logic to select all items
  }
}

State Templates

Template directives for customizing various component states and UI elements.

/**
 * Template directive for placeholder display
 * Access to: placeholder text
 */
@Directive({ selector: '[ng-placeholder-tmp]' })
export class NgPlaceholderTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for "not found" message display
 * Access to: searchTerm, notFoundText
 */
@Directive({ selector: '[ng-notfound-tmp]' })
export class NgNotFoundTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for "type to search" message display
 * Access to: typeToSearchText
 */
@Directive({ selector: '[ng-typetosearch-tmp]' })
export class NgTypeToSearchTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for loading text display
 * Access to: loadingText
 */
@Directive({ selector: '[ng-loadingtext-tmp]' })
export class NgLoadingTextTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for loading spinner display
 * Access to: loading state
 */
@Directive({ selector: '[ng-loadingspinner-tmp]' })
export class NgLoadingSpinnerTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

/**
 * Template directive for clear button customization
 * Access to: clear function
 */
@Directive({ selector: '[ng-clearbutton-tmp]' })
export class NgClearButtonTemplateDirective {
  constructor(public template: TemplateRef<any>) {}
}

Usage Examples:

@Component({
  template: `
    <ng-select 
      [(ngModel)]="selectedItem" 
      [items]="items" 
      bindLabel="name"
      [loading]="isLoading"
      [clearable]="true">
      
      <!-- Custom placeholder with icon -->
      <ng-placeholder-tmp>
        <div class="custom-placeholder">
          <i class="search-icon"></i>
          Choose your favorite option...
        </div>
      </ng-placeholder-tmp>
      
      <!-- Custom not found message -->
      <ng-notfound-tmp ng-notfound-tmp let-searchTerm="searchTerm">
        <div class="not-found">
          <i class="warning-icon"></i>
          <p>No results found for "{{ searchTerm }}"</p>
          <button type="button" (click)="suggestAlternatives(searchTerm)">
            Show suggestions
          </button>
        </div>
      </ng-notfound-tmp>
      
      <!-- Custom loading spinner -->
      <ng-loadingspinner-tmp>
        <div class="custom-loader">
          <div class="spinner"></div>
          <span>Loading awesome data...</span>
        </div>
      </ng-loadingspinner-tmp>
      
      <!-- Custom clear button -->
      <ng-clearbutton-tmp ng-clearbutton-tmp let-clear="clear">
        <button type="button" 
                class="custom-clear-btn" 
                (click)="clear()"
                title="Clear selection">
          <i class="clear-icon"></i>
        </button>
      </ng-clearbutton-tmp>
    </ng-select>
  `
})
export class StateTemplatesComponent {
  selectedItem: any;
  items: any[] = [];
  isLoading: boolean = false;
  
  suggestAlternatives(searchTerm: string) {
    // Custom logic for showing alternative suggestions
  }
}

Template Context Variables

Each template directive provides access to specific context variables:

// Context variables available in templates
interface NgOptionContext {
  $implicit: any;           // The item
  item: any;               // The item (same as $implicit)
  index: number;           // Item index
  searchTerm: string;      // Current search term
}

interface NgLabelContext {
  $implicit: any;          // The selected item
  item: any;              // The selected item
  clear: (item?: any) => void;  // Function to clear item
}

interface NgMultiLabelContext {
  items: any[];           // Array of selected items
  clear: () => void;      // Function to clear all items
}

interface NgNotFoundContext {
  $implicit: string;      // The search term
  searchTerm: string;     // The search term
  notFoundText: string;   // The not found text
}

interface NgHeaderFooterContext {
  searchTerm: string;     // Current search term
  items: any[];          // Current filtered items
}

Template Best Practices

Performance Considerations

// Good: Use OnPush change detection with templates
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <ng-select [items]="items" bindLabel="name">
      <ng-option-tmp ng-option-tmp let-item="item">
        <div class="option">{{ item.name }}</div>
      </ng-option-tmp>
    </ng-select>
  `
})
export class OptimizedTemplateComponent {}

// Good: Use trackBy for better performance with large lists
@Component({
  template: `
    <ng-select [items]="items" [trackByFn]="trackByFn">
      <!-- templates -->
    </ng-select>
  `
})
export class TrackByComponent {
  trackByFn = (index: number, item: any) => item.id;
}

Accessibility

@Component({
  template: `
    <ng-select 
      [items]="items" 
      bindLabel="name"
      ariaLabel="Select user"
      labelForId="user-select">
      
      <ng-option-tmp ng-option-tmp let-item="item" let-index="index">
        <div 
          role="option" 
          [attr.aria-label]="item.name + ', ' + item.role"
          [attr.aria-describedby]="'user-desc-' + index">
          {{ item.name }} - {{ item.role }}
        </div>
      </ng-option-tmp>
    </ng-select>
  `
})
export class AccessibleTemplateComponent {}

docs

configuration-services.md

index.md

ng-option-highlight.md

ng-select-component.md

template-directives.md

types-interfaces.md

tile.json