or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accordion.mdalert.mdcarousel.mddatepicker.mdfeedback.mdforms.mdindex.mdlayout.mdmodal.mdnavigation.md

forms.mddocs/

0

# Form Components

1

2

Enhanced form controls including rating, timepicker, and typeahead components with full Angular forms integration and accessibility support.

3

4

## Core Imports

5

6

```typescript

7

import {

8

NgbRatingModule,

9

NgbTimepickerModule,

10

NgbTypeaheadModule

11

} from '@ng-bootstrap/ng-bootstrap';

12

```

13

14

## Capabilities

15

16

### NgbRating

17

18

Star rating component with customizable appearance and behavior.

19

20

```typescript { .api }

21

@Component({

22

selector: 'ngb-rating',

23

exportAs: 'ngbRating'

24

})

25

class NgbRating implements ControlValueAccessor {

26

/** Maximum rating value */

27

@Input() max: number;

28

29

/** Current rating value */

30

@Input() rate: number;

31

32

/** If true, rating is readonly */

33

@Input() readonly: boolean;

34

35

/** If true, allows resetting to 0 by clicking current rate */

36

@Input() resettable: boolean;

37

38

/** Template for custom star appearance */

39

@Input() starTemplate: TemplateRef<StarTemplateContext>;

40

41

/** Event emitted when hovering over a star */

42

@Output() hover: EventEmitter<number>;

43

44

/** Event emitted when mouse leaves the rating */

45

@Output() leave: EventEmitter<number>;

46

47

/** Event emitted when rating changes */

48

@Output() rateChange: EventEmitter<number>;

49

50

/** Reset rating to 0 */

51

reset(): void;

52

53

/** Update rating value */

54

update(value: number): void;

55

}

56

```

57

58

### NgbTimepicker

59

60

Time picker component for hour, minute, and second selection.

61

62

```typescript { .api }

63

@Component({

64

selector: 'ngb-timepicker',

65

exportAs: 'ngbTimepicker'

66

})

67

class NgbTimepicker implements ControlValueAccessor {

68

/** If true, display 12-hour format with AM/PM */

69

@Input() meridian: boolean;

70

71

/** If true, show spinner buttons */

72

@Input() spinners: boolean;

73

74

/** If true, show seconds input */

75

@Input() seconds: boolean;

76

77

/** Hour step for spinner buttons */

78

@Input() hourStep: number;

79

80

/** Minute step for spinner buttons */

81

@Input() minuteStep: number;

82

83

/** Second step for spinner buttons */

84

@Input() secondStep: number;

85

86

/** If true, inputs are readonly */

87

@Input() readonlyInputs: boolean;

88

89

/** Size of the timepicker */

90

@Input() size: 'small' | 'medium' | 'large';

91

92

/** Navigate to specific time */

93

navigateTime(step: number): void;

94

}

95

```

96

97

### NgbTypeahead

98

99

Autocomplete/typeahead directive providing powerful search functionality for input elements.

100

101

```typescript { .api }

102

@Directive({

103

selector: 'input[ngbTypeahead]',

104

exportAs: 'ngbTypeahead'

105

})

106

class NgbTypeahead implements ControlValueAccessor {

107

/** Autocomplete attribute for the input */

108

@Input() autocomplete: string;

109

110

/** Container element for the dropdown */

111

@Input() container: string;

112

113

/** If false, selected value cannot be edited */

114

@Input() editable: boolean;

115

116

/** If true, first item will be focused automatically */

117

@Input() focusFirst: boolean;

118

119

/** Function to format selected item in input field */

120

@Input() inputFormatter: (item: any) => string;

121

122

/** Operator function that provides search suggestions */

123

@Input() ngbTypeahead: OperatorFunction<string, readonly any[]> | null | undefined;

124

125

/** Function to format items in result list */

126

@Input() resultFormatter: (item: any) => string;

127

128

/** Custom template for result items */

129

@Input() resultTemplate: TemplateRef<ResultTemplateContext>;

130

131

/** If true, selects item on exact match */

132

@Input() selectOnExact: boolean;

133

134

/** If true, shows hint with first match */

135

@Input() showHint: boolean;

136

137

/** Preferred placement of dropdown */

138

@Input() placement: PlacementArray;

139

140

/** Popper options modifier function */

141

@Input() popperOptions: (options: Partial<Options>) => Partial<Options>;

142

143

/** CSS class for dropdown popup */

144

@Input() popupClass: string;

145

146

/** Event emitted when item is selected */

147

@Output() selectItem: EventEmitter<NgbTypeaheadSelectItemEvent>;

148

149

/** Active descendant for accessibility */

150

activeDescendant: string | null;

151

152

/** Popup window ID */

153

popupId: string;

154

155

/** Dismiss the typeahead popup */

156

dismissPopup(): void;

157

158

/** Check if popup is open */

159

isPopupOpen(): boolean;

160

}

161

```

162

163

### NgbHighlight

164

165

Component for highlighting search terms within text results.

166

167

```typescript { .api }

168

@Component({

169

selector: 'ngb-highlight',

170

exportAs: 'ngbHighlight'

171

})

172

class NgbHighlight {

173

/** CSS class for highlighted spans (default: 'ngb-highlight') */

174

@Input() highlightClass: string;

175

176

/** Text to add highlighting to (required) */

177

@Input({ required: true }) result?: string | null;

178

179

/** Term or terms to highlight (required) */

180

@Input({ required: true }) term: string | readonly string[];

181

182

/** If true, highlighting is accent-sensitive */

183

@Input() accentSensitive: boolean;

184

185

/** Array of text parts after processing */

186

parts: string[];

187

}

188

```

189

190

### Configuration Services

191

192

```typescript { .api }

193

@Injectable({ providedIn: 'root' })

194

class NgbRatingConfig {

195

/** Default maximum rating */

196

max: number;

197

198

/** Default readonly state */

199

readonly: boolean;

200

201

/** Default resettable state */

202

resettable: boolean;

203

}

204

205

@Injectable({ providedIn: 'root' })

206

class NgbTimepickerConfig {

207

/** Default meridian setting */

208

meridian: boolean;

209

210

/** Default spinners setting */

211

spinners: boolean;

212

213

/** Default seconds setting */

214

seconds: boolean;

215

216

/** Default hour step */

217

hourStep: number;

218

219

/** Default minute step */

220

minuteStep: number;

221

222

/** Default second step */

223

secondStep: number;

224

225

/** Default disabled state */

226

disabled: boolean;

227

228

/** Default readonly inputs state */

229

readonlyInputs: boolean;

230

231

/** Default size */

232

size: 'small' | 'medium' | 'large';

233

}

234

235

@Injectable({ providedIn: 'root' })

236

class NgbTypeaheadConfig {

237

/** Default container */

238

container: string;

239

240

/** Default editor formatter */

241

editable: boolean;

242

243

/** Default focus first */

244

focusFirst: boolean;

245

246

/** Default show hint */

247

showHint: boolean;

248

249

/** Default placement */

250

placement: PlacementArray;

251

}

252

```

253

254

## Type Definitions

255

256

```typescript { .api }

257

interface NgbTimeStruct {

258

hour: number;

259

minute: number;

260

second: number;

261

}

262

263

interface NgbTypeaheadSelectItemEvent {

264

/** Selected item */

265

item: any;

266

267

/** Prevent default selection behavior */

268

preventDefault: () => void;

269

}

270

271

interface StarTemplateContext {

272

/** Star value/index */

273

$implicit: number;

274

275

/** Current fill percentage (0-100) */

276

fill: number;

277

278

/** Star index */

279

index: number;

280

}

281

282

interface ResultTemplateContext {

283

/** Search result item */

284

$implicit: any;

285

286

/** Search term */

287

term: string;

288

289

/** Formatter function */

290

formatter: (item: any) => string;

291

}

292

```

293

294

## Usage Examples

295

296

### Basic Rating Component

297

298

```typescript

299

@Component({

300

template: `

301

<div class="mb-3">

302

<label>Rate this item:</label>

303

<ngb-rating

304

[(rate)]="currentRate"

305

[max]="5"

306

[readonly]="false"

307

[resettable]="true"

308

(rateChange)="onRateChange($event)">

309

</ngb-rating>

310

<p>Current rating: {{ currentRate }}</p>

311

</div>

312

`

313

})

314

export class BasicRatingComponent {

315

currentRate = 3;

316

317

onRateChange(rate: number) {

318

console.log('Rating changed to:', rate);

319

}

320

}

321

```

322

323

### Custom Star Template

324

325

```typescript

326

@Component({

327

template: `

328

<ngb-rating

329

[(rate)]="currentRate"

330

[starTemplate]="customStar">

331

</ngb-rating>

332

333

<ng-template #customStar let-fill="fill" let-index="index">

334

<span class="custom-star" [class.filled]="fill === 100">

335

<i class="bi" [class.bi-heart-fill]="fill === 100" [class.bi-heart]="fill < 100"></i>

336

</span>

337

</ng-template>

338

`

339

})

340

export class CustomStarRatingComponent {

341

currentRate = 2;

342

}

343

```

344

345

### Basic Timepicker

346

347

```typescript

348

@Component({

349

template: `

350

<div class="mb-3">

351

<label>Select time:</label>

352

<ngb-timepicker

353

[(ngModel)]="selectedTime"

354

[meridian]="true"

355

[seconds]="true"

356

[spinners]="true">

357

</ngb-timepicker>

358

<p *ngIf="selectedTime">Selected: {{ selectedTime | json }}</p>

359

</div>

360

`

361

})

362

export class BasicTimepickerComponent {

363

selectedTime: NgbTimeStruct = { hour: 13, minute: 30, second: 0 };

364

}

365

```

366

367

### Reactive Form Integration

368

369

```typescript

370

@Component({

371

template: `

372

<form [formGroup]="timeForm" (ngSubmit)="onSubmit()">

373

<div class="mb-3">

374

<label>Meeting time:</label>

375

<ngb-timepicker

376

formControlName="meetingTime"

377

[meridian]="false"

378

[seconds]="false">

379

</ngb-timepicker>

380

</div>

381

382

<div class="mb-3">

383

<label>Rating:</label>

384

<ngb-rating

385

formControlName="rating"

386

[max]="10">

387

</ngb-rating>

388

</div>

389

390

<button type="submit" class="btn btn-primary" [disabled]="timeForm.invalid">

391

Submit

392

</button>

393

</form>

394

`

395

})

396

export class ReactiveFormComponent implements OnInit {

397

timeForm: FormGroup;

398

399

constructor(private fb: FormBuilder) {}

400

401

ngOnInit() {

402

this.timeForm = this.fb.group({

403

meetingTime: [{ hour: 14, minute: 0, second: 0 }, Validators.required],

404

rating: [5, [Validators.required, Validators.min(1)]]

405

});

406

}

407

408

onSubmit() {

409

if (this.timeForm.valid) {

410

console.log('Form data:', this.timeForm.value);

411

}

412

}

413

}

414

```

415

416

### Basic Typeahead

417

418

```typescript

419

@Component({

420

template: `

421

<div class="mb-3">

422

<label for="typeahead-basic">Search for a state:</label>

423

<input

424

id="typeahead-basic"

425

type="text"

426

class="form-control"

427

[(ngModel)]="selectedState"

428

[ngbTypeahead]="search"

429

placeholder="Type to search...">

430

</div>

431

432

<p *ngIf="selectedState">Selected: {{ selectedState }}</p>

433

`

434

})

435

export class BasicTypeaheadComponent {

436

selectedState: string = '';

437

438

states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California'];

439

440

search = (text$: Observable<string>) =>

441

text$.pipe(

442

debounceTime(200),

443

distinctUntilChanged(),

444

map(term => term.length < 2 ? []

445

: this.states.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1).slice(0, 10))

446

);

447

}

448

```

449

450

### Advanced Typeahead with Template

451

452

```typescript

453

@Component({

454

template: `

455

<div class="mb-3">

456

<label for="typeahead-template">Search users:</label>

457

<input

458

id="typeahead-template"

459

type="text"

460

class="form-control"

461

[(ngModel)]="selectedUser"

462

[ngbTypeahead]="searchUsers"

463

[resultTemplate]="userTemplate"

464

[inputFormatter]="userFormatter"

465

(selectItem)="onUserSelect($event)">

466

</div>

467

468

<ng-template #userTemplate let-user="result" let-term="term">

469

<div class="d-flex align-items-center">

470

<img [src]="user.avatar" class="rounded-circle me-2" width="32" height="32">

471

<div>

472

<div><ngb-highlight [result]="user.name" [term]="term"></ngb-highlight></div>

473

<small class="text-muted">{{ user.email }}</small>

474

</div>

475

</div>

476

</ng-template>

477

`

478

})

479

export class AdvancedTypeaheadComponent {

480

selectedUser: any;

481

482

users = [

483

{ id: 1, name: 'John Doe', email: 'john@example.com', avatar: 'avatar1.jpg' },

484

{ id: 2, name: 'Jane Smith', email: 'jane@example.com', avatar: 'avatar2.jpg' }

485

];

486

487

searchUsers = (text$: Observable<string>) =>

488

text$.pipe(

489

debounceTime(300),

490

distinctUntilChanged(),

491

map(term => term.length < 2 ? []

492

: this.users.filter(user =>

493

user.name.toLowerCase().includes(term.toLowerCase()) ||

494

user.email.toLowerCase().includes(term.toLowerCase())

495

).slice(0, 10))

496

);

497

498

userFormatter = (user: any) => user.name;

499

500

onUserSelect(event: NgbTypeaheadSelectItemEvent) {

501

console.log('User selected:', event.item);

502

}

503

}

504

```