# @eqproject/eqp-attachments

> Dynamic attachments component - Angular Material based

Latest version **21.0.0** (published 2026-04-29) · 0 weekly downloads

## Install

```sh
npm install @eqproject/eqp-attachments
pnpm add @eqproject/eqp-attachments
yarn add @eqproject/eqp-attachments
bun add @eqproject/eqp-attachments
```

## Health

**Score 55/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 21.0.0 |
| Published | 2026-04-29 |
| First published | 2021-09-09 |
| Weekly downloads | 0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 443 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | EqProject |
| Maintainers | eqp, a.cipollone |

## Links

- npm: https://www.npmjs.com/package/@eqproject/eqp-attachments
- npm.io page: https://npm.io/package/@eqproject/eqp-attachments

## Dependencies (4)

- [tslib](https://npm.io/package/tslib.md) ^2.6.2
- [sweetalert2](https://npm.io/package/sweetalert2.md) ^11.10.1
- [ngx-image-cropper](https://npm.io/package/ngx-image-cropper.md) ^9.1.5
- [browser-image-compression](https://npm.io/package/browser-image-compression.md) ^2.0.2

## Recent versions

- 21.0.0 (latest) — 2026-04-29
- 3.1.15 (v17-lts) — 2026-06-18
- 2.5.4 (v15-lts) — 2025-11-20
- 0.1.18 (ng9) — 2023-08-04
- 3.1.14 — 2026-04-29
- 3.1.13 — 2026-03-06
- 3.1.12 — 2026-03-06
- 3.1.11 — 2026-02-18
- 3.1.10 — 2026-01-29
- 3.1.9 — 2026-01-29
- 3.1.8 — 2026-01-28
- 3.1.7 — 2026-01-21
- 3.1.6 — 2026-01-20
- 3.1.5 — 2026-01-15
- 3.1.4 — 2025-11-11
- … 50 more at https://npm.io/package/@eqproject/eqp-attachments/versions

## README

## Table of Contents

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

* [Overview](#overview)
* [Requirements](#requirements)
* [Getting Started](#getting-started)
* [API Reference](#api-reference)
  * [Inputs](#inputs)
  * [Outputs](#outputs)
  * [Data Models](#data-models)
* [Advanced Features](#advanced-features)
  * [Large File Handling](#large-file-handling)
  * [Video Support](#video-support)
  * [Dynamic Action Control](#dynamic-action-control)
  * [Theming with CSS Custom Properties](#theming-with-css-custom-properties)
* [Use Cases](#use-cases)
* [Credits](#credits)

## 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 with two layout variants (`full` and `compact`).
* **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.
* **Video Support:** Automatic thumbnail generation and optional server-side video compression.
* **Large File Handling:** Files exceeding a configurable byte threshold are stored as a native `File` object instead of Base64, preventing memory issues with large uploads.
* **Extensible Table:** Add custom columns and custom "more options" menu actions to the table view.
* **Granular Action Control:** Show, hide, or disable any built-in or custom action on a per-row basis via hook functions.
* **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 `attachmentsList` for 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'` | `'full'` renders a large centered dropbox area; `'compact'` renders a slim inline uploader bar. |
| `viewMode`           | `'card' \| 'table'`   | `'table'`   | The default display mode for the attachment list.                                |
| `chooseView`         | `boolean` | `true`      | If `true`, displays the Card/Table view switcher in the header.                |
| `showHeader`         | `boolean` | `true`      | If `true`, displays the title in the header when `multipleAttachment` is `true`. |
| `showSummary`        | `boolean` | `false`     | If `true`, displays the summary block with file count and total size.          |
| `showUploadTitle`    | `boolean` | `true`      | If `true`, shows the title above the drop area.                                |
| `showDropArea`       | `boolean` | `true`      | If `false`, hides the entire upload/drop area (useful for read-only display).  |
| `cardSize`           | `'small' \| 'medium' \| 'large' \| 'custom'` | `'small'` | Controls the size of cards in card view. Use `'custom'` with `customCardWidthPx` and `customCardHeightPx`. |
| `customCardWidthPx`  | `number`  | `200`       | Sets the custom card width in pixels when `cardSize` is `'custom'`.          |
| `customCardHeightPx` | `number`  | `180`       | Sets the custom card height in pixels when `cardSize` is `'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.                   |

---

#### **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.        |
| `hiddenColumns`      | `string[]`  | `[]`         | An array of column `key` values to hide from the table view.                 |
| `hiddenActions`      | `string[]`  | `[]`         | An array of action `key` values to hide from the actions menu (e.g., `['delete']`). |
| `showInlinePreview`  | `boolean`   | `false`      | If `true`, shows a thumbnail preview column directly in the table rows.      |
| `isEqpTableMultiLanguage` | `boolean` | `false`   | Enables multilanguage support for the embedded table.                        |
| `tablePaginatorVisible`   | `boolean` | `true`    | If `false`, hides the paginator below the table.                             |
| `isTableSearcheable`      | `boolean` | `true`    | If `false`, hides the search field above the table.                          |
| `tablePaginatorSize`      | `number`  | `null`    | Sets the default page size for the table paginator.                          |

---

#### **Functional Configuration**

| Input                           | Type                 | Default       | Description                                                                                               |
| ------------------------------- | -------------------- | ------------- | --------------------------------------------------------------------------------------------------------- |
| `maxFileSizeMB`               | `number`           | `500`       | Sets the maximum file size in megabytes for each uploaded file. Files exceeding this limit are rejected with a toast notification. |
| `base64LimitMB`               | `number`           | `100`       | Files exceeding this size (MB) are stored as a native `File` object in `LargeFile` instead of being Base64-encoded. See [Large File Handling](#large-file-handling). |
| `loadMultipleFiles`           | `boolean`          | `false`     | If `true`, allows selecting multiple files at once from the file browser.                               |
| `singleAttachmentDragAndDrop` | `boolean`          | `true`      | If `true`, enables the drag-and-drop UI even in single-attachment mode.                                 |
| `showActionButtons`           | `boolean`          | `false`     | If `true`, shows Download/Preview/Delete action buttons below the attachment in single-attachment mode. |
| `isDisabled`                  | `boolean`          | `false`     | Disables all "add attachment" controls.                                                                   |
| `disableAction`               | `boolean`          | `false`     | If `true`, disables the Delete action in both card and table views.                                     |
| `allowOnlyImages`             | `boolean`          | `false`     | If `true`, restricts file uploads to image types only.                                                  |
| `acceptedFileTypes`           | `string`           | `undefined` | A string for the `<input>` `accept` attribute (e.g., `'.pdf,image/*'`).                             |
| `showPreview`                 | `boolean`          | `true`      | Enables the preview functionality for attachments.                                                        |
| `enableImageCrop`             | `boolean`          | `true`      | If `false`, skips the crop dialog and uploads images directly (compression still applies).             |
| `compressionOptions`          | `IOptions`         | `{ maxSizeMB: 0.5, maxWidthOrHeight: 1920, useWebWorker: true }` | Options for client-side image compression. |
| `cropOptions`                 | `CropOptionEnum[]` | `[1, 2]`   | Enables specific tools in the image cropper (1: Rotate, 2: Flip). Pass `[]` to show no tools.        |
| `separatedUploadButtons`      | `boolean`          | `false`     | If `true` and multiple `allowedTypes` are available, shows separate buttons instead of a dropdown menu. |
| `getAttachmentEndpoint`       | `string`           | `null`      | API endpoint (POST) to fetch full attachment data (including `FileDataBase64`) for image previews.     |
| `productionBaseUrl`           | `string`           | `null`      | Base URL used to build a Google Viewer URL for document previews (e.g., PDFs, Word files).            |
| `videoCompression`            | `object`           | `{ enabled: false, ... }` | Configuration for optional server-side video compression. See [Video Support](#video-support). |
| `actionHiddenFn`              | `(actionKey: string, att?: IAttachmentDTO) => boolean` | `undefined` | A global hook to dynamically hide any action (built-in or custom) for a specific attachment. See [Dynamic Action Control](#dynamic-action-control). |
| `actionDisabledFn`            | `(actionKey: string, att?: IAttachmentDTO) => boolean` | `undefined` | A global hook to dynamically disable any action for a specific attachment.                            |

---

#### **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)`               | `void`             | 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.            |
| `FileExtension`       | `string`          | The file extension (e.g., `'pdf'`, `'png'`).         |
| `AttachmentType`      | `AttachmentType`  | The type of attachment (1: FILE, 2: LINK, 3: DROPBOX). |
| `FileDataBase64`      | `string`          | The Base64 content of the file. `null` for large files (see `LargeFile`). |
| `FileContentType`     | `string`          | The MIME type of the file (e.g., `image/png`).       |
| `IsImage`             | `boolean`         | `true` if the attachment is an image.                |
| `FileThumbnailBase64` | `string`          | The Base64 content of a low-resolution thumbnail (auto-generated for videos). |
| `LargeFile`           | `File`            | The native browser `File` object for files exceeding `base64LimitMB`. Used instead of `FileDataBase64`. |
| `IsLargeFile`         | `boolean`         | `true` when the attachment is stored in `LargeFile` rather than `FileDataBase64`. |
| `TrustedUrl`          | `any`             | (Internal State) A `SafeResourceUrl` used for previewing links, PDFs, and videos in the dialog. |
| `isUploading`         | `boolean`         | (Internal State) `true` during the upload process.   |

---


#### `AttachmentFieldColumn` Interface

| Property                | Type                | Description                                            |
| ----------------------- | ------------------- | ------------------------------------------------------ |
| `key`                  | `string` | Unique identifier for the column. Used by `hiddenColumns`.  |
| `display`            | `string`          | The column header label to display.                        |
| `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 using CSS flex shorthand (e.g., `'1 1 0%'` or `'0 0 150px'`). |
| `position`            | `number`          | The column's display order. The built-in "File" column is 10, "Actions" is 100. |
| `class`     | `string`          | A custom CSS class added to every cell in this column.   |
| `hidden`    | `boolean \| (() => boolean)` | If `true` (or if the function returns `true`), the column is excluded from rendering. |

---

#### `AttachmentMenuAction` Interface

| Property                | Type                | Description                                            |
| ----------------------- | ------------------- | ------------------------------------------------------ |
| `key`                   | `string` | Optional unique identifier for the action. Used by `hiddenActions` and `actionHiddenFn`/`actionDisabledFn`. |
| `icon`                  | `string` | `mat-icon` name to display (e.g., `'share'`).         |
| `name`            | `string`          | Text to show in the menu item.                             |
| `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. |
| `hidden`        | `(att: IAttachmentDTO) => boolean`  | Function to dynamically hide the action for a specific row.   |
| `position`      | `number`          | Display order. Built-in "Preview" is 10, "Delete" is 100. Use a number in between to insert a custom action. |

---


#### **AttachmentCardSize Type**

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

---

---

#### **Layout Configuration**

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

---


## Advanced Features

### Large File Handling

By default, files are read as Base64 strings and stored in `IAttachmentDTO.FileDataBase64`. However, for files exceeding the `base64LimitMB` threshold (default: **100 MB**), the component switches strategy to avoid memory exhaustion: the native browser `File` object is stored in `IAttachmentDTO.LargeFile`, and `FileDataBase64` is set to `null`.

When `localEditedAttachments` emits a list containing large files, your backend integration must handle them differently (e.g., via `FormData` multipart upload).

```typescript
onAttachmentsChange(list: IAttachmentDTO[]) {
  for (const att of list) {
    if (att.IsLargeFile && att.LargeFile) {
      // Handle with multipart/form-data upload
      const formData = new FormData();
      formData.append('file', att.LargeFile, att.FileName);
      this.http.post('/api/upload', formData).subscribe();
    } else {
      // Standard Base64 handling
    }
  }
}
```

> **Note:** Video files are always treated as large files regardless of size — they are stored directly in `LargeFile` and a Base64 thumbnail is generated and stored in `FileThumbnailBase64`.

---

### Video Support

The component has first-class support for video attachments:

* **Thumbnail generation:** When a video is selected, the component automatically captures a frame at the 1-second mark and stores it as a JPEG Base64 string in `FileThumbnailBase64`. This thumbnail is displayed in both card and table views.
* **In-browser preview:** Videos stored in `LargeFile` can be played directly in the preview dialog using the native HTML5 `<video>` player.
* **Server-side compression (optional):** Pass the `videoCompression` input to enable compression via an external API endpoint.

```html
<eqp-attachments
  [attachmentsList]="videoList"
  [videoCompression]="compressionConfig"
  (localEditedAttachments)="onAttachmentsChange($event)">
</eqp-attachments>
```

```typescript
compressionConfig = {
  enabled: true,
  maxWidth: 1280,  // Max output width in px
  crf: 23,         // Constant Rate Factor (quality, lower = better)
  preset: 'veryfast',
  maxFps: 30,
  audioBitrate: 128000
};
```

The compression call is a `multipart/form-data` POST to the URL configured inside the component. The response is expected to be a `Blob` (the compressed `.mp4` file).

---

### Dynamic Action Control

For fine-grained control over which actions are available for each attachment in the table view, use the `actionHiddenFn` and `actionDisabledFn` hook inputs. These are called for every action (both built-in and custom) on every row render.

Built-in action keys: `'preview'`, `'delete'`. Custom actions use the `key` field you define in `AttachmentMenuAction`.

```html
<eqp-attachments
  [attachmentsList]="documents"
  [actionHiddenFn]="myHiddenFn"
  [actionDisabledFn]="myDisabledFn"
  (localEditedAttachments)="onAttachmentsChange($event)">
</eqp-attachments>
```

```typescript
// Hide the 'delete' action for already-persisted attachments (those with a numeric ID)
myHiddenFn = (actionKey: string, att: IAttachmentDTO): boolean => {
  if (actionKey === 'delete' && typeof att.ID === 'number' && att.ID > 0) {
    return true;
  }
  return false;
};

// Disable the 'preview' action for attachments without local data
myDisabledFn = (actionKey: string, att: IAttachmentDTO): boolean => {
  if (actionKey === 'preview') {
    return !att.FileDataBase64 && !att.LargeFile;
  }
  return false;
};
```

You can also hide actions by key name using the simpler `hiddenActions` array input, which is evaluated before the hook:

```html
<!-- Always hide the 'delete' button for everyone -->
<eqp-attachments [hiddenActions]="['delete']" ...></eqp-attachments>
```

---

### Theming with CSS Custom Properties

The component exposes a set of CSS custom properties on `:host` that you can override from the parent application to match your design system.

```scss
// In your component or global styles
eqp-attachments {
  --primary-color: #0d6efd;          // Main accent color (buttons, borders, icons)
  --success-color: #198754;          // Toast success / progress fill
  --error-color: #dc3545;            // Toast error color
  --background-light: #f8f9fa;       // Page background tint
  --background-card: #ffffff;        // Card and panel background
  --text-color: #212529;             // Primary text
  --text-color-light: #6c757d;       // Secondary/muted text
  --border-color: rgba(0,0,0,0.12);  // Dividers and card borders
  --shadow-color: rgba(13,110,253,0.15); // Box shadows
  --border-radius: 12px;             // Card and dialog corner radius
  --transition-speed: 0.25s;         // Animation duration
}
```

---

## 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",
    },
    {
      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]="'table'"
  [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',
        display: 'Uploaded By',        // 'display' is the header label
        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',
        display: 'Status',
        type: TypeAttachmentColumn.TEMPLATE,
        externalTemplate: this.statusTemplate, // Pass the ng-template
        styles: { flex: '1 1 0%' },
        position: 30 // Shows after "Uploaded By" (20)
      }
    ];

    this.myCustomActions = [
      {
        key: 'share',           // Optional but recommended for hiddenActions/hooks
        icon: 'share',
        name: 'Share',          // 'name' is the label shown in the menu
        fn: (item) => this.shareAttachment(item),  // 'fn' is the click handler
        position: 25 // Show after "Preview" (10) and before "Delete" (100)
      },
      {
        key: 'rename',
        icon: 'edit',
        name: 'Edit Name',
        fn: (item) => this.renameAttachment(item),
        position: 26
      }
    ];
  }
```


## Credits

This library has been developed by EqProject SRL. For more info, contact: info@eqproject.it

---
_Source: https://npm.io/package/@eqproject/eqp-attachments · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
