npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@eqproject/eqp-attachments

v3.1.13

Published

Dynamic attachments component - Angular Material based

Readme

Table of Contents

=================

Overview

@eqproject/eqp-attachments provides a complete, client-side solution for attachment management, now fully modernized with the latest Angular features.

Key Features:

  • Single or Multiple Attachments: Easily configure the component to handle one or many attachments.
  • Multiple Sources: Supports local file uploads, direct links from the web, and Dropbox integration.
  • Modern UI: A clean, animated drag-and-drop interface.
  • Dual View Mode: Allows users to switch between a responsive Card Grid and a detailed Table View .
  • Image Cropper: A built-in tool for cropping and rotating uploaded images.
  • Client-Side Validation: Set limits on file size, file types, and more.
  • Highly Configurable: Almost every label, button, and feature can be customized via inputs.
  • Purely Client-Side: The component manages attachments locally without requiring a backend connection, emitting the final data for you to handle.

Requirements

  • Angular 17+
  • Angular Material installed and configured in your project.
  • Font Awesome for a complete icon set (optional, but recommended for the best visual experience).

Getting Started

Step 1: Install the Package

Shell

npm install --save @eqproject/eqp-attachments

Step 2: Import the Component

The component is standalone , so you can import it directly into your component or module.

TypeScript

// in your-component.ts or app/shared module
import { EqpAttachmentsModule } from '@eqproject/eqp-attachments';

@Component({
  selector: 'my-feature-component',
  standalone: true,
  imports: [ EqpAttachmentsModule ],
  template: `
    <eqp-attachments
      [attachmentsList]="myAttachments"
      (localEditedAttachments)="onAttachmentsChange($event)">
    </eqp-attachments>
  `
})
export class MyFeatureComponent {
  myAttachments: IAttachmentDTO[] = [];

  onAttachmentsChange(updatedList: IAttachmentDTO[]) {
    this.myAttachments = updatedList;
    console.log('Attachments list updated!', this.myAttachments);
  }
}

Step 3: Add Styles (Optional)

For the best icon display, include Font Awesome in your project's styles, for example, in angular.json:

JSON

"styles": [
  "src/styles.scss",
  "node_modules/@fortawesome/fontawesome-free/css/all.min.css"
],

API Reference

Inputs

Core Configuration

| Input | Type | Default | Description | | ---------------------- | -------------------- | ---------------- | ------------------------------------------------------------------------------------------------- | | attachmentsList | IAttachmentDTO[] | null | The array of attachments to display and manage. | | singleAttachment | IAttachmentDTO | null | An alternative to attachmentsListfor passing a single attachment object in non-multiple mode. | | multipleAttachment | boolean | true | If true, manages a list of attachments. If false, handles only a single attachment. | | allowedTypes | AttachmentType[] | [FILE, LINK] | An array of allowed attachment sources (e.g.,[1, 2, 3]for File, Link, and Dropbox). |


UI & View Configuration

| Input | Type | Default | Description | | ---------------------- | ----------- | ------------- | -------------------------------------------------------------------------------- | | layout | 'full' | 'compact' | 'compact' | | viewMode | 'card' | 'table' | 'card' | | chooseView | boolean | true | If true, displays the Card/Table view switcher in the header. | | showSummary | boolean | true | If true, displays the summary block with file count and total size. | | cardSize | 'small' | 'medium' | 'large' | | customCardWidthPx | number | 200 | Sets the custom card width in pixels when cardSizeis 'custom'. | | customCardHeightPx | number | 180 | Sets the custom card height in pixels when cardSizeis 'custom'. | | showMatCard | boolean | true | If true(and in table mode), the component is rendered inside a mat-card. | | cropDialogClass | string | undefined | Assigns a custom CSS class to the image cropper dialog panel. | | showUploadTitle | boolean | true | If true, will show title over dropbox |

Table View Configuration

| Input | Type | Default | Description | | ---------------------- | ----------- | ------------- | -------------------------------------------------------------------------------- | | customColumns | 'AttachmentFieldColumn[]' | [] | Array to add custom columns to the table view. | | customMenuActions | 'AttachmentMenuAction[]' | [] | Array to add custom actions to the table's "more options" (...) menu.

Functional Configuration

| Input | Type | Default | Description | | ------------------------------- | -------------------- | ------------- | --------------------------------------------------------------------------------------------------------- | | maxFileSizeMB | number | 100 | Sets the maximum file size in megabytes for each uploaded file. | | loadMultipleFiles | boolean | false | If true, allows selecting multiple files at once from the file browser. | | singleAttachmentDragAndDrop | boolean | false | If true, enables the drag-and-drop UI even in single-attachment mode. | | isDisabled | boolean | false | Disables all "add attachment" controls. | | disableAction | boolean | false | If true, hides the actions column in the table view. | | allowOnlyImages | boolean | false | If true, restricts file uploads to image types only. | | acceptedFileTypes | string | undefined | A string for the <input> acceptattribute (e.g.,'.pdf,image/*'). | | showPreview | boolean | true | Enables the preview functionality for attachments. | | compressionOptions | IOptions | {...} | Options for client-side image compression (maxSizeMB,maxWidthOrHeight, etc.). | | cropOptions | CropOptionEnum[] | [] | Enables specific tools in the image cropper (1: Rotate, 2: Flip). | | separatedUploadButtons | boolean | false | If trueand multiple allowedTypesare available, shows separate buttons instead of a dropdown menu. | | getAttachmentEndpoint | string | null | API endpoint to fetch full attachment data for previews. | | productionBaseUrl | string | null | Base URL for the document viewer (e.g., Google Viewer). |


Labels & Text

| Input | Default | | --------------------------------- | --------------------------------------------- | | uploadTitle | 'Upload file' | | uploadSubtitle | 'Drag & drop files or click' | | dropHereLabel | 'Drop files here' | | supportedFormatsLabel | 'Supported formats: JPEG, PNG, PDF...' | | browseFilesLabel | 'Browse files' | | uploadSummaryLabel | 'Attachments List' | | filesLabel | 'Files' | | totalSizeLabel | 'Total Size' | | emptyTableMessage | 'No data found' | | emptyStateLabel | 'No files have been uploaded' | | openLinkLabel | "Open link" | | addButtonLabel | "Add" | | downloadLabel | "Download" | | deleteLabel | "Delete" | | previewLabel | "Preview" | | confirmLabel | "Confirm" | | abortLabel | "Cancel" | | saveLabel | "Save" | | exitLabel | "Exit" | | fileNameLabel | "File name" | | uploadFileLabel | "Upload file" | | uploadWithDropboxLabel | "Upload with Dropbox" | | cropLabel | "Choose the image dimensions" | | removedLabel | 'File removed' | | addedSuccessfullyLabel | 'file(s) uploaded successfully.' | | deleteDialogTitle | null | | deleteDialogMessage | 'Are you sure you want to delete...' | | noImageSelectedErrorMessage | 'You cannot select a file that is not...' | | wrongTypeSelectedErrorMessage | 'The selected file cannot be uploaded.' | | videoPreviewErrorMessage | 'Cannot open a preview of a video file.' | | audioPreviewErrorMessage | 'Cannot open a preview of an audio file.' | | flipHorinzontalLabel | 'Flip horizontally' | | flipVerticalLabel | 'Flip vertically' | | rotateRightLabel | 'Rotate right' | | rotateLeftLabel | 'Rotate left' | | eqpTableSearchText | 'Search' | | downloadTooltipPosition | 'below' |

Outputs

| Output | Event Arguments | Description | | -------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | (localEditedAttachments) | IAttachmentDTO[] | Emits the complete, updated list of attachments whenever a file/link is added or removed. This is the primary output to listen to. | | (downloadAttachment) | IAttachmentDTO | Triggered on a download attempt for an attachment missing its FileDataBase64, allowing the parent component to fetch the data. | | (onDeleteAttachment) | IAttachmentDTO | Emits the attachment object just before it is removed from the list. | | (abortAddAttachment) | any | Fired when the user cancels an action from a modal dialog (e.g., the crop dialog). |

Data Models

IAttachmentDTO Interface

| Property | Type | Description | | ----------------------- | ------------------- | ------------------------------------------------------ | | ID | number \| string | Unique ID of the attachment. | | FileName | string | Name of the file or link. | | FilePath | string | Path of the link or the file on the server. | | AttachmentType | AttachmentType | The type of attachment (1: FILE, 2: LINK, 3: DROPBOX). | | FileDataBase64 | string | The base64 content of the file. | | FileSize | number | The size of the file in bytes. | | FileContentType | string | The mime type of the file (e.g.,image/png). | | IsImage | boolean | trueif the attachment is an image. | | FileThumbnailBase64 | string | The base64 content of a low-resolution thumbnail. | | isUploading | boolean | (Internal State)trueduring the upload process. | | uploadError | boolean | (Internal State)trueif the upload failed. |


AttachmentFieldColumn Interface

| Property | Type | Description | | ----------------------- | ------------------- | ------------------------------------------------------ | | key | string | . | | display | string | The property key from the IAttachmentDTO object | | type | TypeAttachmentColumn | The rendering type (TEXT, DATE, TEMPLATE). Defaults to TEXT. | | externalTemplate | TemplateRef<any> | The ng-template to use (required if type is TEMPLATE). | | styles | { flex: string } | Defines the column width (e.g., '1 1 0%' or '0 0 150px'). | | position | number | The column's display order (Default: 99). File is 10, Actions is 100. | | class | string | A custom CSS class to add to the column's cells. |

AttachmentMenuAction Interface

| Property | Type | Description | | ----------------------- | ------------------- | ------------------------------------------------------ | | icon | string | mat-icon name to display (e.g., 'share'). | | name | string | Text to show in the menu item.object | | fn | (att: IAttachmentDTO) => void | Function to execute when the item is clicked. | | disabled | (att: IAttachmentDTO) => boolean | Function to dynamically disable the action for a specific row. | | position | number | Display order. Preview is 10, Delete is 100. Use a number in between (e.g., 20) to add an action. |

AttachmentCardSize Type

export type AttachmentCardSize = 'small' | 'medium' | 'large' | 'custom';



Layout Configuration

export type Layout = 'full' | 'compact';


Use Cases

Case 1: Single Image Upload

A configuration for uploading a single image, with drag-and-drop and the image cropper enabled.

HTML

<eqp-attachments
  [multipleAttachment]="false"
  [attachmentsList]="singleImage"
  [singleAttachmentDragAndDrop]="true"
  [allowOnlyImages]="true"
  [cropOptions]="[1, 2]"
  [maxFileSizeMB]="10"
  (localEditedAttachments)="onAttachmentsChange($event)">
</eqp-attachments>

TypeScript

import { IAttachmentDTO } from '@eqproject/eqp-attachments';

export class MyComponent {
  singleImage: IAttachmentDTO[] = [];

  onAttachmentsChange(updatedList: IAttachmentDTO[]) {
    // In single mode, the list will contain 0 or 1 item
    this.singleImage = updatedList;
  }
}

Case 2: Multiple Attachments Management

A full-featured configuration for managing multiple types of attachments, starting in card view and allowing the user to switch to table view.

HTML

<eqp-attachments
  [multipleAttachment]="true"
  [attachmentsList]="documentList"
  [allowedTypes]="[1, 2]"
  [viewMode]="'card'"
  [headerTitle]="'Project Documents'"
  [showSummary]="true"
  (localEditedAttachments)="onAttachmentsChange($event)">
</eqp-attachments>

TypeScript

import { IAttachmentDTO, AttachmentType } from '@eqproject/eqp-attachments';

export class MyComponent {
  documentList: IAttachmentDTO[] = [
    {
      ID: 101,
      IsImage: false,
      AttachmentType: AttachmentType.FILE,
      FileName: "Final Report.pdf",
      FileExtension: "pdf",
      FileSize: 1200000 // 1.2 MB
    },
    {
      ID: 102,
      IsImage: false,
      AttachmentType: AttachmentType.LINK,
      FileName: "GitHub Repository",
      FilePath: "https://github.com/...",
    },
  ];

  onAttachmentsChange(updatedList: IAttachmentDTO[]) {
    this.documentList = updatedList;
  }
}

Case 3: Custom Columns

HTML

<eqp-attachments
  [multipleAttachment]="true"
  [attachmentsList]="documentList"
  [allowedTypes]="[1, 2]"
  [viewMode]="'card'"
  [headerTitle]="'Project Documents'"
  [showSummary]="true"
  (localEditedAttachments)="onAttachmentsChange($event)"
  [customColumns]="myCustomColumns"
  [customMenuActions]="myCustomActions">
</eqp-attachments>

<ng-template #statusTemplate let-att>
  <mat-chip-listbox>
    <mat-chip [style.background-color]="att.Status === 'Approved' ? '#c8e6c9' : '#ffcdd2'"
              [style.color]="att.Status === 'Approved' ? '#2e7d32' : '#c62828'">
      {{ att.Status }}
    </mat-chip>
  </mat-chip-listbox>
</ng-template>

TypeScript

@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<any>;
  
  documentList: IAttachmentDTO[] = [
    { 
      ID: 1, 
      FileName: 'report.pdf', 
      FileExtension: 'pdf', 
      UploadUserName: 'Mario Rossi', 
      Status: 'Approved' 
    },
    { 
      ID: 2, 
      FileName: 'schema.zip', 
      FileExtension: 'zip', 
      UploadUserName: 'Laura Bianchi', 
      Status: 'Pending' 
    }
  ];
  myCustomColumns: AttachmentFieldColumn[] = [];
  myCustomActions: AttachmentMenuAction[] = [];

  ngOnInit() {
    this.myCustomColumns = [
      { 
        key: 'UploadUserName', 
        header: 'Uploaded By',
        type: TypeAttachmentColumn.TEXT, // Renders as plain text
        styles: { flex: '2 1 0%' }, // Takes 2 parts of the available space
        position: 20 // Shows after "File" (10)
      },
      {
        key: 'Status', // Unique key for this column
        header: 'Status',
        type: TypeAttachmentColumn.TEMPLATE,
        externalTemplate: this.statusTemplate, // Pass the ng-template
        styles: { flex: '1 1 0%' }, // Takes 1 part of the available space
        position: 30 // Shows after "Uploaded By" (20)
      }
    ];

    this.myCustomActions = [
      {
        icon: 'share',
        label: 'Share',
        onClick: (item) => this.shareAttachment(item),
        position: 25 // Show after "Preview" (10) and before "Delete" (100)
      },
      {
        icon: 'edit',
        label: 'Edit Name',
        onClick: (item) => this.renameAttachment(item),
        position: 26
      }
    ];
  }

Credits

This library has been developed by EqProject SRL. For more info, contact: [email protected]