The Angular CDK Text Field module provides utilities for enhancing text input elements, including autofill detection and automatic textarea resizing functionality.
Monitor and detect when input fields are auto-filled by the browser.
/**
* Service for monitoring input autofill state
*/
class AutofillMonitor implements OnDestroy {
/**
* Monitor an element for autofill changes
* @param elementOrRef - Element to monitor
* @returns Observable that emits autofill events
*/
monitor(elementOrRef: Element | ElementRef<Element>): Observable<AutofillEvent>;
/**
* Stop monitoring an element for autofill changes
* @param elementOrRef - Element to stop monitoring
*/
stopMonitoring(elementOrRef: Element | ElementRef<Element>): void;
}
/**
* Directive for detecting autofill on input elements
*/
class CdkAutofill implements OnDestroy, OnInit {
/**
* Event emitted when the autofill state changes
*/
readonly cdkAutofill: EventEmitter<AutofillEvent>;
}
/**
* Event emitted when autofill state changes
*/
interface AutofillEvent {
/**
* The target element that was autofilled
*/
target: Element;
/**
* Whether the element is currently autofilled
*/
isAutofilled: boolean;
}Usage Example:
import { Component, ElementRef, ViewChild } from '@angular/core';
import { AutofillMonitor } from '@angular/cdk/text-field';
@Component({
template: `
<form>
<input
#emailInput
type="email"
placeholder="Email"
cdkAutofill
(cdkAutofill)="onAutofill($event)"
[class.autofilled]="isEmailAutofilled">
<input
#passwordInput
type="password"
placeholder="Password"
[class.autofilled]="isPasswordAutofilled">
</form>
`,
styles: [`
.autofilled {
background-color: #e8f5e8;
border-color: #4caf50;
}
`]
})
export class AutofillExample {
@ViewChild('emailInput') emailInput!: ElementRef;
@ViewChild('passwordInput') passwordInput!: ElementRef;
isEmailAutofilled = false;
isPasswordAutofilled = false;
constructor(private autofillMonitor: AutofillMonitor) {}
ngAfterViewInit() {
// Monitor email input
this.autofillMonitor.monitor(this.emailInput).subscribe(event => {
this.isEmailAutofilled = event.isAutofilled;
});
// Monitor password input
this.autofillMonitor.monitor(this.passwordInput).subscribe(event => {
this.isPasswordAutofilled = event.isAutofilled;
});
}
onAutofill(event: any) {
console.log('Autofill detected:', event.isAutofilled);
}
ngOnDestroy() {
this.autofillMonitor.stopMonitoring(this.emailInput);
this.autofillMonitor.stopMonitoring(this.passwordInput);
}
}Automatically resize textarea elements based on their content.
/**
* Directive for auto-resizing textarea elements
*/
class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy {
/**
* Minimum number of rows for the textarea
*/
minRows: number;
/**
* Maximum number of rows for the textarea
*/
maxRows: number;
/**
* Whether autosizing is enabled
*/
enabled: boolean;
/**
* Placeholder text for calculating initial size
*/
placeholder: string;
/**
* Force the textarea to resize to fit its content
* @param force - Whether to force resize even if content hasn't changed
*/
resizeToFitContent(force?: boolean): void;
/**
* Reset the textarea to its original size
*/
reset(): void;
/**
* Check if the textarea needs to be resized
*/
_noopInputHandler(): void;
/**
* Get the minimum height for the textarea
*/
_getMinHeight(): number;
/**
* Get the maximum height for the textarea
*/
_getMaxHeight(): number;
}Usage Example:
import { Component } from '@angular/core';
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
@Component({
template: `
<!-- Basic autosize -->
<textarea
cdkTextareaAutosize
placeholder="This textarea will resize automatically...">
</textarea>
<!-- With min/max rows -->
<textarea
cdkTextareaAutosize
cdkAutosizeMinRows="2"
cdkAutosizeMaxRows="5"
placeholder="Min 2 rows, max 5 rows">
</textarea>
<!-- Programmatic control -->
<textarea
#autosize="cdkTextareaAutosize"
cdkTextareaAutosize
[(ngModel)]="content"
placeholder="Programmatically controlled">
</textarea>
<button (click)="autosize.reset()">Reset Size</button>
<button (click)="autosize.resizeToFitContent(true)">Force Resize</button>
<button (click)="toggleAutosize(autosize)">
{{ autosize.enabled ? 'Disable' : 'Enable' }} Autosize
</button>
`
})
export class TextareaAutosizeExample {
content = '';
toggleAutosize(autosize: CdkTextareaAutosize) {
autosize.enabled = !autosize.enabled;
if (autosize.enabled) {
autosize.resizeToFitContent(true);
}
}
}import { Component, ViewChild } from '@angular/core';
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
template: `
<form [formGroup]="commentForm">
<div class="form-field">
<label for="comment">Comment</label>
<textarea
id="comment"
#commentTextarea="cdkTextareaAutosize"
cdkTextareaAutosize
cdkAutofill
(cdkAutofill)="onAutofill($event)"
formControlName="comment"
[cdkAutosizeMinRows]="minRows"
[cdkAutosizeMaxRows]="maxRows"
[placeholder]="placeholder"
[class.autofilled]="isAutofilled"
class="comment-textarea">
</textarea>
<div class="textarea-actions">
<button type="button" (click)="resetSize()">Reset Size</button>
<button type="button" (click)="adjustRows(-1)">Fewer Rows</button>
<button type="button" (click)="adjustRows(1)">More Rows</button>
</div>
<div class="field-info">
<small>
Min: {{ minRows }} rows, Max: {{ maxRows }} rows
{{ isAutofilled ? '(Autofilled)' : '' }}
</small>
</div>
</div>
</form>
`,
styles: [`
.form-field {
margin-bottom: 16px;
}
.comment-textarea {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-family: inherit;
transition: border-color 0.3s;
}
.comment-textarea:focus {
border-color: #2196f3;
outline: none;
}
.comment-textarea.autofilled {
background-color: #fff3cd;
border-color: #ffc107;
}
.textarea-actions {
margin-top: 8px;
display: flex;
gap: 8px;
}
.textarea-actions button {
padding: 4px 8px;
border: 1px solid #ccc;
background: white;
cursor: pointer;
}
.field-info {
margin-top: 4px;
color: #666;
}
`]
})
export class AdvancedTextFieldExample {
@ViewChild('commentTextarea') commentTextarea!: CdkTextareaAutosize;
commentForm = new FormGroup({
comment: new FormControl('')
});
minRows = 3;
maxRows = 8;
placeholder = 'Enter your comment here...';
isAutofilled = false;
onAutofill(event: any) {
this.isAutofilled = event.isAutofilled;
}
resetSize() {
this.commentTextarea.reset();
}
adjustRows(delta: number) {
if (delta > 0) {
this.maxRows = Math.min(this.maxRows + 1, 15);
} else {
this.minRows = Math.max(this.minRows - 1, 1);
}
// Force resize after changing constraints
setTimeout(() => {
this.commentTextarea.resizeToFitContent(true);
});
}
}/**
* Angular module that includes all CDK text field directives and services
*/
class TextFieldModule {}