Overview
The InputFile component provides a modern file upload interface with drag-and-drop support, file type validation, size limits, and status callbacks. It’s perfect for profile pictures, document uploads, and any file-based input needs.
When to Use
Use the InputFile component when you need to:
Upload profile pictures or avatars
Accept document uploads (PDFs, Word docs, etc.)
Validate file types and sizes before upload
Provide drag-and-drop functionality
Track upload status and progress
For multiple file uploads, you can use multiple InputFile instances or handle multiple files through a single instance with custom logic.
Basic Usage
import { InputFile } from 'mat-dynamic-form' ;
const fileInput = new InputFile (
'document' ,
'Upload Document'
);
Common Patterns
Image Upload with File Type Restriction
import { Validators } from '@angular/forms' ;
const profilePicInput = new InputFile (
'profilePic' ,
'Profile Picture'
). apply ({
accept: [ 'png' , 'jpg' , 'jpeg' , 'gif' ],
maxSize: 5000 , // 5 MB in KB
icon: 'account_circle' ,
validator: Validators . required ,
hint: 'Upload a profile picture (max 5MB)'
});
Document Upload
const documentInput = new InputFile (
'resume' ,
'Upload Resume'
). apply ({
accept: [ 'pdf' , 'doc' , 'docx' ],
maxSize: 10000 , // 10 MB
icon: 'description' ,
validator: Validators . required ,
hint: 'PDF, DOC, or DOCX (max 10MB)'
});
File Upload with Custom Labels
const fileInput = new InputFile (
'attachment' ,
'Attach File'
). apply ({
dragLabel: 'Drag & drop your file here or click to browse' ,
downloadHint: 'Download file' ,
removeHint: 'Remove file' ,
retryHint: 'Retry upload' ,
icon: 'attach_file'
});
File Upload with Status Tracking
import { FileChange } from 'mat-dynamic-form' ;
const fileInput = new InputFile (
'photo' ,
'Upload Photo'
). apply ({
accept: [ 'png' , 'jpg' , 'jpeg' ],
maxSize: 3000 ,
onStatusChange : ( change : FileChange ) => {
console . log ( 'File status:' , change . status );
console . log ( 'File:' , change . file );
switch ( change . status ) {
case 'added' :
console . log ( 'File selected:' , change . file . name );
break ;
case 'uploading' :
console . log ( 'Uploading...' );
break ;
case 'uploaded' :
console . log ( 'Upload complete!' );
break ;
case 'error' :
console . error ( 'Upload failed:' , change . error );
break ;
case 'removed' :
console . log ( 'File removed' );
break ;
}
}
});
File Upload with Initial Value
const fileInput = new InputFile (
'avatar' ,
'Avatar' ,
'https://example.com/avatar.jpg' // Existing file URL
). apply ({
filename: 'current-avatar.jpg' ,
accept: [ 'png' , 'jpg' , 'jpeg' ],
hint: 'Change your avatar'
});
Properties
Unique identifier for the file input.
Label text for the file input.
Initial file value. Can be a file URL string or File object.
Array of allowed file extensions (without dots). Example: ['pdf', 'jpg', 'png']
Default or current filename to display.
Maximum file size in kilobytes (KB). Example: 5000 for 5MB.
Text shown in the drag-and-drop area.
Tooltip text for the download button.
Tooltip text for the remove button.
Tooltip text for the retry button (shown on upload error).
onStatusChange
(change: FileChange) => void
Callback function triggered when file status changes.
Whether the file input is read-only.
Material icon name to display.
validator
ValidatorFn | ValidatorFn[]
Angular validators to apply.
Custom error message shown when validation fails.
Helper text displayed below the file input.
Whether the file input is disabled.
Whether the file input takes up a full row in the form grid.
FileChange Interface
The onStatusChange callback receives a FileChange object:
interface FileChange {
status : 'added' | 'uploading' | 'uploaded' | 'error' | 'removed' ;
file ?: File ;
error ?: any ;
progress ?: number ; // Upload progress (0-100)
}
Validation Examples
Required File
import { Validators } from '@angular/forms' ;
const fileInput = new InputFile ( 'document' , 'Upload Document' ). apply ({
validator: Validators . required ,
errorMessage: 'Please upload a document'
});
Custom File Type Validator
import { AbstractControl , ValidationErrors } from '@angular/forms' ;
function imageFileValidator ( control : AbstractControl ) : ValidationErrors | null {
if ( ! control . value ) return null ;
const file = control . value as File ;
if ( ! file . type . startsWith ( 'image/' )) {
return { notImage: true };
}
return null ;
}
const fileInput = new InputFile ( 'photo' , 'Photo' ). apply ({
validator: [ Validators . required , imageFileValidator ],
errorMessage: 'Please upload an image file'
});
File Size Validator
function maxFileSizeValidator ( maxSizeKB : number ) {
return ( control : AbstractControl ) : ValidationErrors | null => {
if ( ! control . value ) return null ;
const file = control . value as File ;
const fileSizeKB = file . size / 1024 ;
if ( fileSizeKB > maxSizeKB ) {
return { fileSize: { max: maxSizeKB , actual: Math . round ( fileSizeKB ) } };
}
return null ;
};
}
const fileInput = new InputFile ( 'upload' , 'Upload File' ). apply ({
validator: [ Validators . required , maxFileSizeValidator ( 5000 )],
errorMessage: 'File size must not exceed 5MB'
});
Working with Files
Getting Uploaded File
const formData = formStructure . getValue ();
const uploadedFile = formData . document ; // File object
if ( uploadedFile instanceof File ) {
console . log ( 'Filename:' , uploadedFile . name );
console . log ( 'Size:' , uploadedFile . size , 'bytes' );
console . log ( 'Type:' , uploadedFile . type );
console . log ( 'Last modified:' , new Date ( uploadedFile . lastModified ));
}
Uploading File to Server
import { HttpClient } from '@angular/common/http' ;
const formData = structure . getValue ();
const file = formData . document ;
if ( file instanceof File ) {
const uploadData = new FormData ();
uploadData . append ( 'file' , file , file . name );
this . http . post ( '/api/upload' , uploadData ). subscribe (
response => console . log ( 'Upload successful' , response ),
error => console . error ( 'Upload failed' , error )
);
}
Reading File Content
const file = formData . document as File ;
// Read as text
const reader = new FileReader ();
reader . onload = ( e ) => {
const content = e . target ?. result as string ;
console . log ( 'File content:' , content );
};
reader . readAsText ( file );
// Read as Data URL (for images)
const imageReader = new FileReader ();
imageReader . onload = ( e ) => {
const dataUrl = e . target ?. result as string ;
// Use dataUrl to preview image
this . imagePreview = dataUrl ;
};
imageReader . readAsDataURL ( file );
Complete Example
import { Component } from '@angular/core' ;
import { Validators } from '@angular/forms' ;
import { HttpClient } from '@angular/common/http' ;
import { FormStructure , Input , InputFile , Button , FileChange } from 'mat-dynamic-form' ;
@ Component ({
selector: 'app-profile-form' ,
template: '<mat-dynamic-form [structure]="formStructure"></mat-dynamic-form>'
})
export class ProfileFormComponent {
formStructure : FormStructure ;
uploadProgress : number = 0 ;
constructor ( private http : HttpClient ) {
this . formStructure = new FormStructure ( 'Update Profile' );
this . formStructure . appearance = 'outline' ;
this . formStructure . nodeGrid = 2 ;
this . formStructure . nodes = [
new Input ( 'name' , 'Full Name' ). apply ({
icon: 'person' ,
validator: Validators . required ,
singleLine: true
}),
new InputFile (
'profilePicture' ,
'Profile Picture'
). apply ({
accept: [ 'png' , 'jpg' , 'jpeg' ],
maxSize: 5000 , // 5 MB
dragLabel: 'Drag & drop your profile picture here' ,
downloadHint: 'Download current picture' ,
removeHint: 'Remove picture' ,
retryHint: 'Try again' ,
icon: 'account_circle' ,
hint: 'PNG, JPG or JPEG (max 5MB)' ,
singleLine: false ,
onStatusChange : ( change : FileChange ) => this . handleFileChange ( change )
}),
new InputFile (
'resume' ,
'Resume/CV'
). apply ({
accept: [ 'pdf' , 'doc' , 'docx' ],
maxSize: 10000 , // 10 MB
dragLabel: 'Upload your resume' ,
icon: 'description' ,
hint: 'PDF, DOC or DOCX (max 10MB)' ,
singleLine: true
})
];
this . formStructure . validateActions = [
new Button ( 'submit' , 'Save Profile' , {
style: 'primary' ,
onEvent : ( param ) => this . onSubmit ( param . structure )
}). apply ({
validateForm: true ,
icon: 'save'
})
];
}
handleFileChange ( change : FileChange ) {
switch ( change . status ) {
case 'added' :
console . log ( 'File selected:' , change . file ?. name );
this . validateFileType ( change . file ! );
break ;
case 'uploading' :
console . log ( 'Upload progress:' , change . progress , '%' );
this . uploadProgress = change . progress || 0 ;
break ;
case 'uploaded' :
console . log ( 'Upload complete!' );
this . uploadProgress = 100 ;
break ;
case 'error' :
console . error ( 'Upload error:' , change . error );
alert ( 'Upload failed. Please try again.' );
break ;
case 'removed' :
console . log ( 'File removed' );
this . uploadProgress = 0 ;
break ;
}
}
validateFileType ( file : File ) {
const allowedTypes = [ 'image/png' , 'image/jpeg' , 'image/jpg' ];
if ( ! allowedTypes . includes ( file . type )) {
alert ( 'Please upload a PNG or JPEG image' );
// Reset the file input
this . formStructure . patchValue ({ profilePicture: null });
}
}
onSubmit ( structure : FormStructure ) {
const data = structure . getValue ();
const formData = new FormData ();
formData . append ( 'name' , data . name );
if ( data . profilePicture instanceof File ) {
formData . append ( 'profilePicture' , data . profilePicture , data . profilePicture . name );
}
if ( data . resume instanceof File ) {
formData . append ( 'resume' , data . resume , data . resume . name );
}
this . http . post ( '/api/profile' , formData ). subscribe (
response => {
console . log ( 'Profile updated:' , response );
alert ( 'Profile updated successfully!' );
},
error => {
console . error ( 'Update failed:' , error );
alert ( 'Failed to update profile' );
}
);
}
}
Best Practices
Always validate file types - Use the accept property to restrict file types and prevent unwanted uploads:accept : [ 'pdf' , 'jpg' , 'png' ]
Set reasonable file size limits - Protect your server and improve user experience:maxSize : 5000 // 5 MB is reasonable for images
maxSize : 10000 // 10 MB for documents
Handle upload errors gracefully - Use onStatusChange to track upload status and provide feedback:onStatusChange : ( change ) => {
if ( change . status === 'error' ) {
alert ( 'Upload failed. Please try again.' );
}
}
Provide clear hints about requirements :hint : 'PNG or JPEG only, max 5MB'
hint : 'PDF, DOC, or DOCX accepted (max 10MB)'
Use descriptive drag labels - Make it clear what users should do:dragLabel : 'Drag & drop your resume here or click to browse'
Validate on both client and server - Client-side validation improves UX, but always validate on the server for security.
Show upload progress - For large files, show progress to keep users informed:onStatusChange : ( change ) => {
if ( change . status === 'uploading' ) {
console . log ( `Upload progress: ${ change . progress } %` );
}
}
Common File Types
Images
accept : [ 'png' , 'jpg' , 'jpeg' , 'gif' , 'webp' , 'svg' ]
Documents
accept : [ 'pdf' , 'doc' , 'docx' , 'txt' , 'rtf' ]
Spreadsheets
accept : [ 'xls' , 'xlsx' , 'csv' ]
Compressed Files
accept : [ 'zip' , 'rar' , '7z' , 'tar' , 'gz' ]
Audio
accept : [ 'mp3' , 'wav' , 'ogg' , 'm4a' ]
Video
accept : [ 'mp4' , 'avi' , 'mov' , 'wmv' , 'webm' ]
File Size Helper
// Convert MB to KB for maxSize
function mbToKb ( mb : number ) : number {
return mb * 1024 ;
}
// Example usage
const fileInput = new InputFile ( 'file' , 'Upload File' ). apply ({
maxSize: mbToKb ( 5 ) // 5 MB
});
Input Standard text input for file paths or URLs
Textarea For file descriptions or notes
See Also