{"id":13627271,"url":"https://github.com/ngneat/dialog","last_synced_at":"2025-05-14T19:09:06.791Z","repository":{"id":37094365,"uuid":"271253512","full_name":"ngneat/dialog","owner":"ngneat","description":"👻 A simple to use, highly customizable, and powerful modal for Angular Applications","archived":false,"fork":false,"pushed_at":"2024-12-02T17:05:27.000Z","size":2468,"stargazers_count":399,"open_issues_count":15,"forks_count":39,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-07T18:15:37.421Z","etag":null,"topics":["angular","dialog","modal"],"latest_commit_sha":null,"homepage":"https://ngneat.github.io/dialog/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ngneat.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.config.js","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"ngneat"}},"created_at":"2020-06-10T11:01:02.000Z","updated_at":"2025-03-27T13:07:42.000Z","dependencies_parsed_at":"2024-11-07T00:22:40.752Z","dependency_job_id":"e2dac3ab-70d4-4493-8caa-fd4a99dc8a53","html_url":"https://github.com/ngneat/dialog","commit_stats":{"total_commits":182,"total_committers":21,"mean_commits":8.666666666666666,"dds":0.6593406593406593,"last_synced_commit":"40c8f52987b8786124567288c029c3909c8a0a9f"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Fdialog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Fdialog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Fdialog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Fdialog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngneat","download_url":"https://codeload.github.com/ngneat/dialog/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253873039,"owners_count":21976995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","dialog","modal"],"created_at":"2024-08-01T22:00:32.254Z","updated_at":"2025-05-14T19:09:04.835Z","avatar_url":"https://github.com/ngneat.png","language":"TypeScript","funding_links":["https://github.com/sponsors/ngneat"],"categories":["Third Party Components","Projects by main language"],"sub_categories":["Modals","angular"],"readme":"\u003cp align=\"center\"\u003e\n \u003cimg width=\"20%\" height=\"20%\" src=\"./logo.svg\"\u003e\n\u003c/p\u003e\n\u003cbr /\u003e\n\n\u003e A simple to use, highly customizable, and powerful modal for Angular Applications\n\n[![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?style=flat-square)]()\n[![commitizen](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)]()\n[![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)]()\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)\n[![ngneat](https://img.shields.io/badge/@-ngneat-383636?style=flat-square\u0026labelColor=8f68d4)](https://github.com/ngneat/)\n[![spectator](https://img.shields.io/badge/tested%20with-spectator-2196F3.svg?style=flat-square)]()\n\n## Features\n\n✅ \u0026nbsp;TemplateRef/Component Support  \n✅ \u0026nbsp;Dialog Guards Support  \n✅ \u0026nbsp;Resizable  \n✅ \u0026nbsp;Draggable  \n✅ \u0026nbsp;Multiple Dialogs Support  \n✅ \u0026nbsp;Customizable\n\n## Installation\n\n`npm i @ngneat/dialog`\n\n## Usage\n\n### Using a Component\n\nFirst, create the component to be displayed in the modal:\n\n```ts\nimport { DialogService, DialogRef } from '@ngneat/dialog';\n\ninterface Data {\n  title: string;\n}\n\n@Component({\n  template: `\n    \u003ch1\u003e{{ title }}\u003c/h1\u003e\n    \u003cbutton (click)=\"ref.close(true)\"\u003eClose\u003c/button\u003e\n  `,\n  standalone: true,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class HelloWorldComponent {\n  ref: DialogRef\u003cData, boolean\u003e = inject(DialogRef);\n\n  get title() {\n    if (!this.ref.data) return 'Hello world';\n    return this.ref.data.title;\n  }\n}\n```\n\nInside the component, you'll have access to a `DialogRef` provider. You can call its `close()` method to close the current modal. You can also pass `data` that'll be available for any subscribers to `afterClosed$`.\n\n\u003e 💡 Tip\n\u003e\n\u003e A publicly accessible property of type `DialogRef\u003cInput, Output\u003e` on your component will be used to infer the input and output types of your component.\n\nNow we can use the `DialogService` to open the modal and display the component:\n\n```ts\nimport { DialogService } from '@ngneat/dialog';\n\n@Component({\n  standalone: true,\n  template: ` \u003cbutton (click)=\"open()\"\u003eOpen\u003c/button\u003e `,\n})\nexport class AppComponent implements OnInit {\n  private dialog = inject(DialogService);\n\n  ngOnInit() {\n    const dialogRef = this.dialog.open(HelloWorldComponent, {\n      // data is typed based on the passed generic\n      data: {\n        title: '',\n      },\n    });\n  }\n}\n```\n\n### DialogRef API\n\nThe `DialogRef` instance exposes the following API:\n\n- `afterClosed$` - An observable that emits after the modal closes:\n\n```ts\nconst dialogRef = this.dialog.open(HelloWorldComponent);\ndialogRef.afterClosed$.subscribe((result) =\u003e {\n  console.log(`After dialog has been closed ${result}`);\n});\n```\n\n- `backdropClick$` - An observable that emits when the user clicks on the modal backdrop:\n\n```ts\nconst dialogRef = this.dialog.open(HelloWorldComponent);\ndialogRef.backdropClick$.subscribe(() =\u003e {\n  console.log('Backdrop has been clicked');\n});\n```\n\n- `resetDrag` - A method that can be called to reset the dragged modal to the middle of the screen. An offset can be given as the first parameter to position it different from the center:\n\n```ts\ndialogRef.resetDrag();\ndialogRef.resetDrag({ x: 100, y: 0 });\n```\n\n- `beforeClose` - A guard that should return a `boolean`, an `observable`, or a `promise` indicating whether the modal can be closed:\n\n```ts\ndialogRef.beforeClose((result) =\u003e dialogCanBeClosed);\ndialogRef.beforeClose((result) =\u003e this.service.someMethod(result));\n```\n\n- `ref.data` - A reference to the `data` that is passed by the component opened in the modal:\n\n```ts\nimport { DialogService, DialogRef } from '@ngneat/dialog';\n\n@Component({\n  template: `\n    \u003ch1\u003e{{ ref.data.title }}\u003c/h1\u003e\n    \u003cbutton (click)=\"ref.close()\"\u003eClose\u003c/button\u003e\n  `,\n  standalone: true,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class HelloWorldComponent {\n  ref: DialogRef\u003cData\u003e = inject(DialogRef);\n}\n```\n\n- `ref.updateConfig` - An update function for the config, a common use case would be a reusable component setting its own common properties:\n\n```ts\nimport { DialogService, DialogRef } from '@ngneat/dialog';\n\n@Component({\n  template: `\n    \u003ch1\u003e{{ ref.data.title }}\u003c/h1\u003e\n    \u003cbutton (click)=\"ref.close()\"\u003eClose\u003c/button\u003e\n  `,\n  standalone: true,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MyVeryCommonDialogComponent {\n  ref: DialogRef\u003cData\u003e = inject(DialogRef);\n\n  constructor() {\n    this.ref.updateConfig({\n      height: '200px',\n      width: '400px',\n    });\n  }\n}\n```\n\n\u003e You can only update the config before the dialog is opened in the component's constructor.\n\nThe library also provides the `dialogClose` directive helper, that you can use to close the modal:\n\n```ts\nimport { DialogService, DialogCloseDirective } from '@ngneat/dialog';\n\n@Component({\n  standalone: true,\n  imports: [DialogCloseDirective],\n  template: `\n    \u003ch1\u003eHello World\u003c/h1\u003e\n    \u003cbutton dialogClose\u003eClose\u003c/button\u003e\n    \u003cbutton [dialogClose]=\"result\"\u003eClose with result\u003c/button\u003e\n  `,\n})\nexport class HelloWorldComponent {}\n```\n\n### Using a TemplateRef\n\nSometimes it can be overkill to create a whole component. In these cases, you can pass a reference to an `\u003cng-template\u003e`:\n\n```ts\nimport { DialogService } from '@ngneat/dialog';\n\n@Component({\n  selector: 'app-root',\n  standalone: true,\n  template: `\n    \u003cng-template #modalTpl let-ref\u003e\n      \u003ch1\u003eHello World\u003c/h1\u003e\n\n      \u003cbutton (click)=\"ref.close()\"\u003eClose\u003c/button\u003e\n    \u003c/ng-template\u003e\n\n    \u003cbutton (click)=\"open(modalTpl)\"\u003eOpen\u003c/button\u003e\n  `,\n})\nexport class AppComponent {\n  private dialog = inject(DialogService);\n\n  open(tpl: TemplateRef\u003cany\u003e) {\n    this.dialog.open(tpl);\n  }\n}\n```\n\nNote that in this case, you can access the `ref` object by using the `$implicit` context property.\n\n### Passing Data to the Modal Component\n\nSometimes we need to pass data from the opening component to our modal component. In these cases, we can use the `data` property, and use it to pass any data we need:\n\n```ts\nimport { DialogService } from '@ngneat/dialog';\n\n@Component({\n  standalone: true,\n  template: ` \u003cbutton (click)=\"open()\"\u003eOpen\u003c/button\u003e `,\n})\nexport class AppComponent implements OnInit {\n  private dialog = inject(DialogService);\n  private title = 'Dialog title';\n\n  open() {\n    const dialogRef = this.dialog.open(HelloWorldComponent, {\n      data: {\n        title: this.title,\n      },\n    });\n  }\n}\n```\n\nNow we can access it inside our modal component or template, by using the `ref.data` property.\n\n## Dialog Options\n\n### Global Options\n\nIn the `forRoot` method when importing the dialog module in the app module you can specify the following options that will be globally applied to all dialog instances.\n\n- `closeButton` - Whether to display an 'X' for closing the modal (default is true).\n- `enableClose` - Whether a click on the backdrop, or press of the escape button, should close the modal (default is true), see [enable close](#enable-close).\n- `backdrop` - Whether to show the backdrop element (default is true).\n- `resizable` - Whether the modal show be resizeable (default is false).\n- `draggable` - Whether the modal show be draggable (default is false).\n- `draggableConstraint` - When draggable true, whether the modal should be constraint to the window. Use `none` for no constraint, `bounce` to have the modal bounce after it is released and `constrain` to constrain while dragging (default is `none`).\n- `size` - Set the modal size according to your global [custom sizes](#custom-sizes) (default is `md`).\n- `windowClass` - Add a custom class to the modal container.\n- `width` - Set a custom width (default unit is `px`).\n- `minWidth` - Set a custom min-width (default unit is `px`).\n- `maxWidth` - Set a custom max-width (default unit is `px`).\n- `height` - Set a custom height (default unit is `px`).\n- `minHeight` - Set a custom min-height (default unit is `px`).\n- `maxHeight` - Set a custom max-height (default unit is `px`).\n- `container` - A custom element to which we append the modal (default is `body`).\n\n```ts\nimport { provideDialogConfig } from '@ngneat/dialog';\n\nbootstrapApplication(AppComponent, {\n  providers: [\n    provideDialogConfig({\n      closeButton: boolean,\n      enableClose:\n        boolean |\n        'onlyLastStrategy' |\n        {\n          escape: boolean | 'onlyLastStrategy',\n          backdrop: boolean | 'onlyLastStrategy',\n        },\n      backdrop: boolean,\n      resizable: boolean,\n      draggable: boolean,\n      overflow: boolean,\n      draggableConstraint: none | bounce | constrain,\n      sizes,\n      size: sm | md | lg | fullScreen | string,\n      windowClass: string,\n      width: string | number,\n      minWidth: string | number,\n      maxWidth: string | number,\n      height: string | number,\n      minHeight: string | number,\n      maxHeight: string | number,\n    }),\n  ],\n});\n```\n\n### Instance Options\n\nFor each dialog instance you open you can specify all the global options and also the following 3 options.\n\n- `id` - The modal's unique id, the defaults are:\n  - If a component is passed - the component's name (e.g. `MyCustomDialog`).\n  - Otherwise, a random id is given.\n\u003e [!Note]  \n\u003e while not required, it is recommended to set an id in order to prevent unwanted multiple instances of the same dialog.\n- `vcr` - A custom `ViewContainerRef` to use.\n- `data` - A `data` object that will be passed to the modal template or component.\n\n```ts\nthis.dialog.open(compOrTemplate, {\n  //...\n  // all global options expect sizes\n  //...\n  id: string,\n  vcr: ViewContainerRef,\n  data: {},\n});\n```\n\n### Enable close\n\nThe `enableClose` property can be configured for each dialog.\nIt can either be an object with the keys `escape` and `backdrop` for more granular control,\nor one of the values described below directly.\nThe latter will apply the set value to both close triggers (escape and backdrop).\n\nIf set to `true`, clicking on the backdrop or pressing the escape key will close the modal.\nIf set to `false`, this behavior will be disabled.\n\nAdditionally, the property can be set to the string value `'onlyLastStrategy'`.\nIn this case, the behavior will only apply to the last dialog that was opened, and not to any other dialog.\nBy default, this should be the top-most dialog and behave as `true`.\n\n## Custom Sizes\n\nThe default `sizes` config is:\n\n```ts\n{\n  sizes: {\n    sm: {\n      height: 'auto',\n        width: '400px',\n    },\n    md: {\n      height: 'auto',\n        width: '560px',\n    },\n    lg: {\n      height: 'auto',\n        width: '800px',\n    },\n    fullScreen: {\n      height: '100%',\n        width: '100%',\n    },\n  }\n}\n```\n\nYou can override it globally by using the `sizes` option:\n\n```ts\nbootstrapApplication(AppComponent, {\n  providers: [\n    provideDialogConfig({\n      sizes: {\n        sm: {\n          width: 300, // 300px\n          minHeight: 250, // 250px\n        },\n        md: {\n          width: '60vw',\n          height: '60vh',\n        },\n        lg: {\n          width: '90vw',\n          height: '90vh',\n        },\n        fullScreen: {\n          width: '100vw',\n          height: '100vh',\n        },\n      },\n    }),\n  ],\n});\n```\n\n## Styling\n\nYou can customize the styles with these classes:\n\n```scss\nngneat-dialog {\n  .ngneat-dialog-backdrop {\n    // backdrop styles\n    .ngneat-dialog-content {\n      // dialog content, where your component/template is placed\n      .ngneat-drag-marker {\n        // draggable marker\n      }\n      .ngneat-close-dialog {\n        // 'X' icon for closing the dialog\n      }\n    }\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Fdialog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngneat%2Fdialog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Fdialog/lists"}