or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-services.mdindex.mdng-option-highlight.mdng-select-component.mdtemplate-directives.mdtypes-interfaces.md

template-directives.mddocs/

0

# Template Customization

1

2

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.

3

4

## Capabilities

5

6

### Item Display Templates

7

8

Template directives for customizing how items and selections are displayed.

9

10

```typescript { .api }

11

/**

12

* Template directive for customizing individual option display in dropdown

13

* Access to: item, item.label, item.value, item.disabled, index, searchTerm

14

*/

15

@Directive({ selector: '[ng-option-tmp]' })

16

export class NgOptionTemplateDirective {

17

constructor(public template: TemplateRef<any>) {}

18

}

19

20

/**

21

* Template directive for customizing selected item label display

22

* Access to: item, clear function, item.label, item.value

23

*/

24

@Directive({ selector: '[ng-label-tmp]' })

25

export class NgLabelTemplateDirective {

26

constructor(public template: TemplateRef<any>) {}

27

}

28

29

/**

30

* Template directive for customizing multi-select label display

31

* Access to: items array, clear function

32

*/

33

@Directive({ selector: '[ng-multi-label-tmp]' })

34

export class NgMultiLabelTemplateDirective {

35

constructor(public template: TemplateRef<any>) {}

36

}

37

38

/**

39

* Directive for displaying and styling item labels with automatic HTML escaping

40

* Alternative to using bindLabel property - provides more control over display

41

*/

42

@Directive({ selector: '[ngItemLabel]' })

43

export class NgItemLabelDirective implements OnChanges {

44

/** The label text to display */

45

@Input() ngItemLabel: string;

46

/** Whether to escape HTML in the label (default: true) */

47

@Input() escape: boolean = true;

48

49

constructor(private element: ElementRef<HTMLElement>) {}

50

51

ngOnChanges(changes: SimpleChanges): void;

52

}

53

54

/**

55

* Template directive for customizing option group display

56

* Access to: item (group), item.label, item.children

57

*/

58

@Directive({ selector: '[ng-optgroup-tmp]' })

59

export class NgOptgroupTemplateDirective {

60

constructor(public template: TemplateRef<any>) {}

61

}

62

63

/**

64

* Template directive for customizing tag display when addTag is enabled

65

* Access to: searchTerm, item

66

*/

67

@Directive({ selector: '[ng-tag-tmp]' })

68

export class NgTagTemplateDirective {

69

constructor(public template: TemplateRef<any>) {}

70

}

71

```

72

73

**Usage Examples:**

74

75

```typescript

76

@Component({

77

template: `

78

<!-- Custom option template with icons and descriptions -->

79

<ng-select [(ngModel)]="selectedUser" [clearable]="false">

80

<ng-option *ngFor="let user of users" [value]="user">

81

<ng-container *ngOptionTemplateDirective="let item=item; let index=index">

82

<div class="user-option">

83

<img [src]="item.avatar" width="24" height="24" class="avatar">

84

<div class="user-info">

85

<div class="name">{{ item.name }}</div>

86

<div class="email">{{ item.email }}</div>

87

</div>

88

<span class="role-badge">{{ item.role }}</span>

89

</div>

90

</ng-container>

91

</ng-option>

92

93

<!-- Custom selected label template -->

94

<ng-label-tmp ng-label-tmp let-item="item" let-clear="clear">

95

<img [src]="item.avatar" width="18" height="18">

96

{{ item.name }}

97

<span class="clear-btn" (click)="clear(item)">×</span>

98

</ng-label-tmp>

99

</ng-select>

100

101

<!-- Multi-select with custom multi-label -->

102

<ng-select [(ngModel)]="selectedUsers" [multiple]="true">

103

<ng-option *ngFor="let user of users" [value]="user">

104

{{ user.name }}

105

</ng-option>

106

107

<ng-multi-label-tmp ng-multi-label-tmp let-items="items" let-clear="clear">

108

<div class="multi-label">

109

<span class="selected-count">{{ items.length }} users selected</span>

110

<span class="clear-all" (click)="clear()">Clear all</span>

111

</div>

112

</ng-multi-label-tmp>

113

</ng-select>

114

`

115

})

116

export class CustomTemplatesComponent {

117

selectedUser: any;

118

selectedUsers: any[] = [];

119

users = [

120

{

121

id: 1,

122

name: 'Alice Johnson',

123

email: 'alice@example.com',

124

avatar: '/avatars/alice.jpg',

125

role: 'Admin'

126

},

127

// ... more users

128

];

129

}

130

```

131

132

### Layout Templates

133

134

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

135

136

```typescript { .api }

137

/**

138

* Template directive for dropdown header content

139

* Access to: searchTerm, items

140

*/

141

@Directive({ selector: '[ng-header-tmp]' })

142

export class NgHeaderTemplateDirective {

143

constructor(public template: TemplateRef<any>) {}

144

}

145

146

/**

147

* Template directive for dropdown footer content

148

* Access to: searchTerm, items

149

*/

150

@Directive({ selector: '[ng-footer-tmp]' })

151

export class NgFooterTemplateDirective {

152

constructor(public template: TemplateRef<any>) {}

153

}

154

```

155

156

**Usage Examples:**

157

158

```typescript

159

@Component({

160

template: `

161

<ng-select [(ngModel)]="selectedItem" [items]="items" bindLabel="name">

162

<!-- Custom header with search stats -->

163

<ng-header-tmp>

164

<div class="dropdown-header">

165

<h4>Select an Item</h4>

166

<small *ngIf="searchTerm">

167

Showing results for "{{ searchTerm }}"

168

</small>

169

</div>

170

</ng-header-tmp>

171

172

<!-- Custom footer with action buttons -->

173

<ng-footer-tmp>

174

<div class="dropdown-footer">

175

<button type="button" (click)="addNewItem()">Add New Item</button>

176

<button type="button" (click)="selectAll()">Select All</button>

177

</div>

178

</ng-footer-tmp>

179

</ng-select>

180

`

181

})

182

export class HeaderFooterComponent {

183

selectedItem: any;

184

searchTerm: string = '';

185

items = [/* ... */];

186

187

addNewItem() {

188

// Custom logic to add new item

189

}

190

191

selectAll() {

192

// Custom logic to select all items

193

}

194

}

195

```

196

197

### State Templates

198

199

Template directives for customizing various component states and UI elements.

200

201

```typescript { .api }

202

/**

203

* Template directive for placeholder display

204

* Access to: placeholder text

205

*/

206

@Directive({ selector: '[ng-placeholder-tmp]' })

207

export class NgPlaceholderTemplateDirective {

208

constructor(public template: TemplateRef<any>) {}

209

}

210

211

/**

212

* Template directive for "not found" message display

213

* Access to: searchTerm, notFoundText

214

*/

215

@Directive({ selector: '[ng-notfound-tmp]' })

216

export class NgNotFoundTemplateDirective {

217

constructor(public template: TemplateRef<any>) {}

218

}

219

220

/**

221

* Template directive for "type to search" message display

222

* Access to: typeToSearchText

223

*/

224

@Directive({ selector: '[ng-typetosearch-tmp]' })

225

export class NgTypeToSearchTemplateDirective {

226

constructor(public template: TemplateRef<any>) {}

227

}

228

229

/**

230

* Template directive for loading text display

231

* Access to: loadingText

232

*/

233

@Directive({ selector: '[ng-loadingtext-tmp]' })

234

export class NgLoadingTextTemplateDirective {

235

constructor(public template: TemplateRef<any>) {}

236

}

237

238

/**

239

* Template directive for loading spinner display

240

* Access to: loading state

241

*/

242

@Directive({ selector: '[ng-loadingspinner-tmp]' })

243

export class NgLoadingSpinnerTemplateDirective {

244

constructor(public template: TemplateRef<any>) {}

245

}

246

247

/**

248

* Template directive for clear button customization

249

* Access to: clear function

250

*/

251

@Directive({ selector: '[ng-clearbutton-tmp]' })

252

export class NgClearButtonTemplateDirective {

253

constructor(public template: TemplateRef<any>) {}

254

}

255

```

256

257

**Usage Examples:**

258

259

```typescript

260

@Component({

261

template: `

262

<ng-select

263

[(ngModel)]="selectedItem"

264

[items]="items"

265

bindLabel="name"

266

[loading]="isLoading"

267

[clearable]="true">

268

269

<!-- Custom placeholder with icon -->

270

<ng-placeholder-tmp>

271

<div class="custom-placeholder">

272

<i class="search-icon"></i>

273

Choose your favorite option...

274

</div>

275

</ng-placeholder-tmp>

276

277

<!-- Custom not found message -->

278

<ng-notfound-tmp ng-notfound-tmp let-searchTerm="searchTerm">

279

<div class="not-found">

280

<i class="warning-icon"></i>

281

<p>No results found for "{{ searchTerm }}"</p>

282

<button type="button" (click)="suggestAlternatives(searchTerm)">

283

Show suggestions

284

</button>

285

</div>

286

</ng-notfound-tmp>

287

288

<!-- Custom loading spinner -->

289

<ng-loadingspinner-tmp>

290

<div class="custom-loader">

291

<div class="spinner"></div>

292

<span>Loading awesome data...</span>

293

</div>

294

</ng-loadingspinner-tmp>

295

296

<!-- Custom clear button -->

297

<ng-clearbutton-tmp ng-clearbutton-tmp let-clear="clear">

298

<button type="button"

299

class="custom-clear-btn"

300

(click)="clear()"

301

title="Clear selection">

302

<i class="clear-icon"></i>

303

</button>

304

</ng-clearbutton-tmp>

305

</ng-select>

306

`

307

})

308

export class StateTemplatesComponent {

309

selectedItem: any;

310

items: any[] = [];

311

isLoading: boolean = false;

312

313

suggestAlternatives(searchTerm: string) {

314

// Custom logic for showing alternative suggestions

315

}

316

}

317

```

318

319

### Template Context Variables

320

321

Each template directive provides access to specific context variables:

322

323

```typescript { .api }

324

// Context variables available in templates

325

interface NgOptionContext {

326

$implicit: any; // The item

327

item: any; // The item (same as $implicit)

328

index: number; // Item index

329

searchTerm: string; // Current search term

330

}

331

332

interface NgLabelContext {

333

$implicit: any; // The selected item

334

item: any; // The selected item

335

clear: (item?: any) => void; // Function to clear item

336

}

337

338

interface NgMultiLabelContext {

339

items: any[]; // Array of selected items

340

clear: () => void; // Function to clear all items

341

}

342

343

interface NgNotFoundContext {

344

$implicit: string; // The search term

345

searchTerm: string; // The search term

346

notFoundText: string; // The not found text

347

}

348

349

interface NgHeaderFooterContext {

350

searchTerm: string; // Current search term

351

items: any[]; // Current filtered items

352

}

353

```

354

355

## Template Best Practices

356

357

### Performance Considerations

358

359

```typescript

360

// Good: Use OnPush change detection with templates

361

@Component({

362

changeDetection: ChangeDetectionStrategy.OnPush,

363

template: `

364

<ng-select [items]="items" bindLabel="name">

365

<ng-option-tmp ng-option-tmp let-item="item">

366

<div class="option">{{ item.name }}</div>

367

</ng-option-tmp>

368

</ng-select>

369

`

370

})

371

export class OptimizedTemplateComponent {}

372

373

// Good: Use trackBy for better performance with large lists

374

@Component({

375

template: `

376

<ng-select [items]="items" [trackByFn]="trackByFn">

377

<!-- templates -->

378

</ng-select>

379

`

380

})

381

export class TrackByComponent {

382

trackByFn = (index: number, item: any) => item.id;

383

}

384

```

385

386

### Accessibility

387

388

```typescript

389

@Component({

390

template: `

391

<ng-select

392

[items]="items"

393

bindLabel="name"

394

ariaLabel="Select user"

395

labelForId="user-select">

396

397

<ng-option-tmp ng-option-tmp let-item="item" let-index="index">

398

<div

399

role="option"

400

[attr.aria-label]="item.name + ', ' + item.role"

401

[attr.aria-describedby]="'user-desc-' + index">

402

{{ item.name }} - {{ item.role }}

403

</div>

404

</ng-option-tmp>

405

</ng-select>

406

`

407

})

408

export class AccessibleTemplateComponent {}

409

```