A comprehensive Angular component for managing file attachments with upload, download, preview, and organization features.
npm install ngx-st-attachmentsngx-st-attachments component provides a complete solution for file attachment management with features including:
bash
npm install ngx-st-attachments
`
Import the module in your application:
`typescript
import { NgxStAttachmentsModule } from 'ngx-st-attachments';
@NgModule({
imports: [
NgxStAttachmentsModule
]
})
export class AppModule { }
`
---
Basic Usage
`html
[attachments]="attachments"
[accessToken]="token"
[downloadLink]="downloadUrl"
[uploadLink]="uploadUrl"
[canCrudActions]="true"
(newAttachments)="onAttachmentsChanged($event)">
`
`typescript
export class MyComponent {
attachments: AttachmentModel[] = [];
token = 'your-access-token';
downloadUrl = 'https://api.example.com/download?token=';
uploadUrl = 'https://api.example.com/upload';
onAttachmentsChanged(attachments: AttachmentModel[]) {
this.attachments = attachments;
// Handle attachment changes
}
}
`
---
Inputs
$3
#### attachments
- Type: AttachmentModel[]
- Default: []
- Description: Array of existing attachments to display.
- Example:
`typescript
[attachments]="fileList"
`
#### sourceType
- Type: 'Attachment' | 'Image' | 'Signature'
- Default: 'Attachment'
- Description: Type of files being managed, affects validation and display.
- Example:
`typescript
sourceType="Image"
`
#### title
- Type: string
- Default: ''
- Description: Title displayed above the attachments component.
- Example:
`typescript
title="Project Documents"
`
$3
#### showAddAttachment
- Type: boolean (model)
- Default: false
- Description: Controls visibility of the file upload section. Use two-way binding.
- Example:
`typescript
[(showAddAttachment)]="showUploader"
`
#### multiple
- Type: boolean
- Default: false
- Description: Allows multiple file selection during upload.
- Example:
`typescript
[multiple]="true"
`
#### maxFiles
- Type: number | null
- Default: null
- Description: Maximum number of files that can be uploaded at once. Null means unlimited.
- Example:
`typescript
[maxFiles]="5"
`
#### allowExtensions
- Type: string[]
- Default: ['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'rtf', 'txt', 'bmp']
- Description: List of allowed file extensions.
- Example:
`typescript
[allowExtensions]="['pdf', 'docx', 'xlsx']"
`
#### customFileUploader
- Type: (files: File[]) => Observable
- Default: undefined
- Description: Custom file upload function. If not provided, uses default upload to uploadLink.
- Example:
`typescript
[customFileUploader]="uploadFiles"
uploadFiles(files: File[]): Observable {
const formData = new FormData();
files.forEach(f => formData.append('files', f));
return this.http.post('/api/upload', formData);
}
`
$3
#### canCrudActions
- Type: boolean
- Default: true
- Description: Shows/hides action buttons (download, edit, delete).
- Example:
`typescript
[canCrudActions]="hasEditPermission"
`
#### showTable
- Type: boolean
- Default: true
- Description: Shows/hides the attachments table.
- Example:
`typescript
[showTable]="true"
`
#### showAddDescription
- Type: boolean
- Default: true
- Description: Allows adding/editing file descriptions.
- Example:
`typescript
[showAddDescription]="true"
`
#### showAddGroup
- Type: boolean
- Default: false
- Description: Enables file grouping functionality with group column in table.
- Example:
`typescript
[showAddGroup]="true"
[groupList]="availableGroups"
`
#### groupList
- Type: AttachmentGroupModel[]
- Default: []
- Description: List of available groups for organizing attachments.
- Example:
`typescript
[groupList]="groups"
groups: AttachmentGroupModel[] = [
{ id: '1', name: 'Invoices' },
{ id: '2', name: 'Contracts' }
];
`
$3
#### downloadLink
- Type: string
- Default: ''
- Description: Base URL for downloading files. Component appends &id={attachmentId}.
- Example:
`typescript
downloadLink="https://api.example.com/download?token=xxx"
`
#### uploadLink
- Type: string
- Default: ''
- Description: URL endpoint for file uploads (used with default uploader).
- Example:
`typescript
uploadLink="https://api.example.com/upload"
`
#### accessToken
- Type: string
- Default: ''
- Description: Authentication token for API requests.
- Example:
`typescript
[accessToken]="authToken"
`
$3
#### showGeneratePublicLink
- Type: boolean
- Default: false
- Description: Shows button to generate public sharing links for files.
- Example:
`typescript
[showGeneratePublicLink]="true"
[generatePublicLinkAction]="generateLink"
`
#### generatePublicLinkAction
- Type: (id: string) => Observable
- Default: undefined
- Description: Function to generate public links for file sharing.
- Example:
`typescript
[generatePublicLinkAction]="generatePublicLink"
generatePublicLink(id: string): Observable {
return this.http.post(
/api/attachments/${id}/public-link,
{}
);
}
`
#### usePwaDownload
- Type: boolean
- Default: false
- Description: Uses PWA-compatible download method with fetch API instead of direct links.
- Example:
`typescript
[usePwaDownload]="true"
`
#### isOffline
- Type: boolean
- Default: false
- Description: Enables offline mode, downloads files from base64 data stored in attachment model.
- Example:
`typescript
[isOffline]="!navigator.onLine"
`
$3
#### labelTexts
- Type: AttachmentLabelTextsModel
- Default: English labels (see model below)
- Description: Customizable labels for all UI text in the component.
- Example:
`typescript
[labelTexts]="customLabels"
customLabels: AttachmentLabelTextsModel = {
browseFile: 'Browse',
dropHere: 'Drop files here',
uploading: 'Uploading...',
fileSelectedCount: 'file(s) selected',
tableFileName: 'File Name',
tableDescription: 'Description',
sizeError: 'File too large (max 20 MB)',
extensionError: 'Invalid file type',
editDescriptionTitle: 'Edit Description',
close: 'Close',
save: 'Save',
groupLabel: 'Group',
publicLinkTitle: 'Public Links',
showPublicLinkLabel: 'View Link',
getPublicLinkLabel: 'Download Link',
publicLinkCopied: 'Link copied!',
isInternalLabel: 'Internal Only'
};
`
---
Outputs
$3
- Type: EventEmitter
- Description: Emitted when attachments are added, removed, or modified. Contains the complete updated array of attachments.
- Example:
`typescript
(newAttachments)="onAttachmentsChanged($event)"
onAttachmentsChanged(attachments: AttachmentModel[]) {
this.attachments = attachments;
this.saveAttachments(attachments);
}
`
---
Models
$3
`typescript
interface AttachmentModel {
id: string; // Unique identifier
extension: string; // File extension (e.g., 'pdf', 'jpg')
contentType: string; // MIME type
size: number; // File size in bytes
sourceFileName: string; // Original filename
sourceType: string; // Type: 'Attachment', 'Image', 'Signature'
description: string; // User-provided description
fileBase64?: string; // Base64 data for offline mode
group: AttachmentGroupModel | null; // File group/category
isInternal: boolean; // Internal-only flag
}
`
$3
`typescript
interface AttachmentGroupModel {
id: string; // Group identifier
name: string; // Group display name
}
`
$3
`typescript
interface AttachmentLabelTextsModel {
browseFile: string;
dropHere: string;
uploading: string;
fileSelectedCount: string;
tableFileName: string;
tableDescription: string;
sizeError: string;
extensionError: string;
editDescriptionTitle: string;
close: string;
save: string;
groupLabel: string;
publicLinkTitle: string;
showPublicLinkLabel: string;
getPublicLinkLabel: string;
publicLinkCopied: string;
isInternalLabel: string;
}
`
$3
`typescript
interface GeneratePublicLinkResponseModel {
viewLink: string; // URL for viewing the file
downloadLink: string; // URL for downloading the file
}
`
---
Features
$3
Users can drag files directly onto the upload area or click to browse.
$3
- Validates file size (default max 20MB)
- Validates file extensions against allowExtensions
- Shows error messages for invalid files
$3
- Image files can be previewed in a dialog
- Works in both online and offline modes
$3
- Add descriptions to files
- Group files into categories
- Mark files as internal-only
$3
- Standard download links
- PWA-compatible downloads (fetch API)
- Offline mode (from base64 data)
$3
- Generate shareable public links
- Separate view and download links
- Copy to clipboard functionality
---
Examples
$3
`html
[attachments]="documents"
[canCrudActions]="true"
[multiple]="true"
[showAddDescription]="true"
(newAttachments)="documents = $event">
`
$3
`html
sourceType="Image"
[attachments]="images"
[showAddGroup]="true"
[groupList]="imageGroups"
[allowExtensions]="['jpg', 'jpeg', 'png', 'gif']"
title="Project Images"
(newAttachments)="onImagesUpdated($event)">
`
$3
`typescript
export class DocumentsComponent {
attachments: AttachmentModel[] = [];
token = this.authService.getToken();
constructor(private http: HttpClient, private authService: AuthService) {}
customUpload = (files: File[]): Observable => {
const formData = new FormData();
files.forEach(file => formData.append('files', file));
return this.http.post(
'/api/documents/upload',
formData,
{
headers: { 'Authorization': Bearer ${this.token} }
}
);
}
generateLink = (id: string): Observable => {
return this.http.post(
/api/documents/${id}/share,
{}
);
}
}
`
`html
[attachments]="attachments"
[customFileUploader]="customUpload"
[showGeneratePublicLink]="true"
[generatePublicLinkAction]="generateLink"
[accessToken]="token"
(newAttachments)="attachments = $event">
`
$3
`html
[attachments]="offlineAttachments"
[isOffline]="true"
[canCrudActions]="false"
[showAddAttachment]="false">
`
`typescript
// Attachments with base64 data for offline viewing
offlineAttachments: AttachmentModel[] = [
{
id: '1',
sourceFileName: 'document.pdf',
extension: 'pdf',
fileBase64: 'data:application/pdf;base64,...',
// ... other fields
}
];
`
$3
`typescript
germanLabels: AttachmentLabelTextsModel = {
browseFile: 'Datei durchsuchen',
dropHere: 'oder Datei hier ablegen',
uploading: 'Hochladen',
fileSelectedCount: 'Datei(en) ausgewählt',
tableFileName: 'Dateiname',
tableDescription: 'Beschreibung',
sizeError: 'Datei größer als maximal zulässige Länge == 20 MB',
extensionError: 'Falsche Dateierweiterung',
editDescriptionTitle: 'Dateibeschreibung bearbeiten',
close: 'Schließen',
save: 'Speichern',
groupLabel: 'Gruppe',
publicLinkTitle: 'Öffentliche Links',
showPublicLinkLabel: 'Link anzeigen',
getPublicLinkLabel: 'Download-Link',
publicLinkCopied: 'Link in Zwischenablage kopiert',
isInternalLabel: 'Nur intern'
};
`
`html
[attachments]="attachments"
[labelTexts]="germanLabels"
(newAttachments)="attachments = $event">
`
---
Build
Run ng build ngx-st-attachments to build the project. The build artifacts will be stored in the dist/ directory.
Publishing
After building your library with ng build ngx-st-attachments, go to the dist folder cd dist/ngx-st-attachments and run npm publish`.