Overview
The Textarea component extends the standard Input component to provide multi-line text entry. It’s perfect for comments, descriptions, addresses, and any content that requires more than one line.
When to Use
Use the Textarea component when you need to:
Capture comments, feedback, or descriptions
Enter multi-line addresses
Write longer text content (bio, notes, etc.)
Provide space for detailed explanations
For single-line text, use Input instead. Textarea inherits all Input properties and methods.
Basic Usage
import { TextArea } from 'mat-dynamic-form' ;
const commentArea = new TextArea (
'comments' ,
'Comments'
);
Common Patterns
Textarea with Character Limit
import { Validators } from '@angular/forms' ;
const bioArea = new TextArea (
'bio' ,
'Biography' ,
'' ,
500 // maxCharCount
). apply ({
icon: 'description' ,
validator: Validators . required ,
hint: 'Tell us about yourself (max 500 characters)'
});
The character counter appears automatically when maxCharCount is set.
Textarea with Validation
const feedbackArea = new TextArea (
'feedback' ,
'Your Feedback' ,
'' ,
1000
). apply ({
icon: 'feedback' ,
validator: [ Validators . required , Validators . minLength ( 10 )],
errorMessage: 'Please provide at least 10 characters of feedback' ,
hint: 'We value your input'
});
Full-Width Textarea
const descriptionArea = new TextArea (
'description' ,
'Product Description' ,
'' ,
2000
). apply ({
singleLine: true , // Takes full row width
icon: 'notes' ,
validator: Validators . required ,
hint: 'Provide a detailed product description'
});
Read-Only Textarea
const termsArea = new TextArea (
'terms' ,
'Terms and Conditions' ,
'These are the terms...'
). apply ({
readOnly: true ,
singleLine: true ,
hint: 'Please read carefully'
});
Textarea with Value Change Handler
const messageArea = new TextArea (
'message' ,
'Message' ,
'' ,
500
). apply ({
icon: 'message' ,
action: {
type: 'valueChange' ,
onEvent : ( param ) => {
const text = param . event ;
const wordCount = text . trim (). split ( / \s + / ). length ;
console . log ( 'Word count:' , wordCount );
// Show warning if too long
if ( text . length > 450 ) {
console . warn ( 'Approaching character limit' );
}
}
}
});
Properties
Unique identifier for the textarea.
Placeholder text shown when the textarea is empty.
Initial value of the textarea.
Maximum number of characters allowed. Shows a character counter.
Minimum number of characters required.
Whether the textarea is read-only.
Material icon name to display (e.g., 'notes', 'description', 'message').
validator
ValidatorFn | ValidatorFn[]
Angular validators to apply.
Custom error message shown when validation fails.
Helper text displayed below the textarea.
Whether the textarea is disabled.
Whether the textarea takes up a full row in the form grid.
Whether the textarea receives focus when the form loads.
Methods
editable()
Makes the textarea editable by setting readOnly to false.
const textarea = new TextArea ( 'field' , 'Field' ). apply ({ readOnly: true });
// Later, make it editable
textarea . editable ();
readonly()
Makes the textarea read-only by setting readOnly to true.
const textarea = new TextArea ( 'field' , 'Field' );
// Make it read-only
textarea . readonly ();
apply()
Applies multiple properties at once.
textarea . apply ({
icon: 'notes' ,
validator: Validators . required ,
maxCharCount: 500 ,
hint: 'Enter your text here'
});
getNativeElement()
Returns the native DOM element.
const element = textarea . getNativeElement ();
if ( element ) {
element . focus ();
}
Validation Examples
Required Textarea
import { Validators } from '@angular/forms' ;
const textarea = new TextArea ( 'comments' , 'Comments' , '' , 500 ). apply ({
validator: Validators . required ,
errorMessage: 'Comments are required'
});
Min/Max Length Validation
const textarea = new TextArea ( 'description' , 'Description' , '' , 1000 ). apply ({
validator: [
Validators . required ,
Validators . minLength ( 50 ),
Validators . maxLength ( 1000 )
],
errorMessage: 'Description must be between 50 and 1000 characters'
});
Pattern Validation (No Special Characters)
const textarea = new TextArea ( 'notes' , 'Notes' , '' , 500 ). apply ({
validator: [
Validators . required ,
Validators . pattern ( / ^ [ a-zA-Z0-9\s.,!?- ] * $ / )
],
errorMessage: 'Only letters, numbers, and basic punctuation allowed'
});
Word Count Validator
import { AbstractControl , ValidationErrors } from '@angular/forms' ;
function wordCountValidator ( min : number , max : number ) {
return ( control : AbstractControl ) : ValidationErrors | null => {
if ( ! control . value ) return null ;
const wordCount = control . value . trim (). split ( / \s + / ). filter (( w : string ) => w . length > 0 ). length ;
if ( wordCount < min ) {
return { minWords: { required: min , actual: wordCount } };
}
if ( wordCount > max ) {
return { maxWords: { required: max , actual: wordCount } };
}
return null ;
};
}
const textarea = new TextArea ( 'essay' , 'Essay' , '' , 5000 ). apply ({
validator: [ Validators . required , wordCountValidator ( 100 , 500 )],
errorMessage: 'Essay must be between 100 and 500 words' ,
hint: 'Write 100-500 words'
});
Complete Example
import { Component } from '@angular/core' ;
import { Validators } from '@angular/forms' ;
import { FormStructure , Input , TextArea , Dropdown , OptionChild , Button } from 'mat-dynamic-form' ;
@ Component ({
selector: 'app-feedback-form' ,
template: '<mat-dynamic-form [structure]="formStructure"></mat-dynamic-form>'
})
export class FeedbackFormComponent {
formStructure : FormStructure ;
constructor () {
this . formStructure = new FormStructure ( 'Submit Feedback' );
this . formStructure . appearance = 'outline' ;
this . formStructure . nodeGrid = 2 ;
this . formStructure . nodes = [
new Input ( 'name' , 'Your Name' ). apply ({
icon: 'person' ,
validator: Validators . required ,
singleLine: true
}),
new Input ( 'email' , 'Email Address' ). apply ({
icon: 'email' ,
validator: [ Validators . required , Validators . email ],
singleLine: true
}),
new Dropdown (
'category' ,
'Feedback Category' ,
[
new OptionChild ( 'Bug Report' , 'bug' ),
new OptionChild ( 'Feature Request' , 'feature' ),
new OptionChild ( 'General Feedback' , 'general' ),
new OptionChild ( 'Complaint' , 'complaint' )
]
). apply ({
icon: 'category' ,
validator: Validators . required ,
singleLine: true
}),
new Input ( 'subject' , 'Subject' ). apply ({
icon: 'subject' ,
validator: Validators . required ,
maxCharCount: 100 ,
singleLine: true
}),
new TextArea (
'message' ,
'Your Message' ,
'' ,
1000
). apply ({
icon: 'message' ,
validator: [ Validators . required , Validators . minLength ( 20 )],
errorMessage: 'Please provide at least 20 characters' ,
hint: 'Describe your feedback in detail (max 1000 characters)' ,
singleLine: true
}),
new TextArea (
'steps' ,
'Steps to Reproduce (for bugs)' ,
'' ,
500
). apply ({
icon: 'list' ,
hint: 'Optional: Help us understand the issue' ,
singleLine: true
})
];
this . formStructure . validateActions = [
new Button ( 'reset' , 'Clear Form' , {
style: 'warn' ,
onEvent : ( param ) => {
param . structure . reset ();
param . structure . remapValues ();
}
}). apply ({
icon: 'clear'
}),
new Button ( 'submit' , 'Submit Feedback' , {
style: 'primary' ,
onEvent : ( param ) => this . onSubmit ( param . structure )
}). apply ({
validateForm: true ,
icon: 'send'
})
];
}
onSubmit ( structure : FormStructure ) {
const data = structure . getValue ();
console . log ( 'Feedback:' , data );
// Submit to API
// this.feedbackService.submit(data).subscribe(...);
alert ( 'Thank you for your feedback!' );
structure . reset ();
structure . remapValues ();
}
}
Best Practices
Set appropriate character limits - Balance between giving users enough space and preventing excessive input:maxCharCount : 500 // For short descriptions
maxCharCount : 2000 // For longer content
Use full width for longer content - Textareas benefit from more horizontal space:singleLine : true // Takes full row width
Provide helpful hints - Guide users on what to write:hint : 'Describe the issue in detail'
hint : 'Include any relevant background information'
Don’t set maxCharCount too low - Users get frustrated when they can’t express themselves. 500+ is a good starting point.
Consider minimum length validation - For critical fields, ensure users provide enough detail:validator : [ Validators . required , Validators . minLength ( 20 )]
Use appropriate icons :
'notes' - General notes/text
'description' - Descriptions
'message' - Messages/comments
'feedback' - Feedback
'comment' - Comments
Common Use Cases
Address Entry
const addressArea = new TextArea (
'address' ,
'Address' ,
'' ,
200
). apply ({
icon: 'location_on' ,
validator: Validators . required ,
hint: 'Enter your complete address' ,
singleLine: true
});
Product Description
const descriptionArea = new TextArea (
'description' ,
'Product Description' ,
'' ,
2000
). apply ({
icon: 'inventory' ,
validator: [ Validators . required , Validators . minLength ( 50 )],
hint: 'Provide a detailed description (at least 50 characters)' ,
singleLine: true
});
User Bio
const bioArea = new TextArea (
'bio' ,
'About Me' ,
'' ,
500
). apply ({
icon: 'person' ,
hint: 'Tell us about yourself (max 500 characters)'
});
const commentArea = new TextArea (
'comment' ,
'Leave a Comment' ,
'' ,
1000
). apply ({
icon: 'comment' ,
validator: [ Validators . required , Validators . minLength ( 5 )],
hint: 'Share your thoughts' ,
singleLine: true
});
Textarea vs Input
Choose between Textarea and Input based on content length:
Use Case Component Reason Name, email, phone Input Single line is sufficient Comments, feedback Textarea Multi-line needed Address Textarea Multiple lines typical URL Input Single line Description Textarea Usually longer content Username Input Always single line Bio Textarea Multiple sentences
Input For single-line text entry
Input File For file uploads with descriptions
See Also