{"id":13627303,"url":"https://github.com/ngneat/overview","last_synced_at":"2025-10-19T17:14:48.339Z","repository":{"id":45310077,"uuid":"321994239","full_name":"ngneat/overview","owner":"ngneat","description":"🤖 A collection of tools to make your Angular views more modular, scalable, and maintainable","archived":false,"fork":false,"pushed_at":"2025-03-31T08:14:20.000Z","size":3659,"stargazers_count":123,"open_issues_count":5,"forks_count":7,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-29T22:23:16.559Z","etag":null,"topics":["angular","dynamic","teleport","views"],"latest_commit_sha":null,"homepage":"","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.md","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-12-16T13:40:41.000Z","updated_at":"2025-04-29T06:30:26.000Z","dependencies_parsed_at":"2024-11-06T19:36:23.521Z","dependency_job_id":"7f476396-b88c-4c3b-892e-258dd5b56979","html_url":"https://github.com/ngneat/overview","commit_stats":{"total_commits":79,"total_committers":7,"mean_commits":"11.285714285714286","dds":0.6075949367088608,"last_synced_commit":"fc085144c20978bfc000f19e919375709c6713e9"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Foverview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Foverview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Foverview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngneat%2Foverview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngneat","download_url":"https://codeload.github.com/ngneat/overview/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252303255,"owners_count":21726378,"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","dynamic","teleport","views"],"created_at":"2024-08-01T22:00:32.638Z","updated_at":"2025-10-19T17:14:48.282Z","avatar_url":"https://github.com/ngneat.png","language":"TypeScript","readme":"\u003cp align=\"center\"\u003e\n \u003cimg width=\"20%\" height=\"20%\" src=\"./logo.svg\"\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n[![npm](https://img.shields.io/npm/v/@ngneat/overview?style=flat-square)](https://www.npmjs.com/package/@ngneat/overview)\n[![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?style=flat-square)](https://github.com/ngneat/overview/blob/main/LICENSE)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/ngneat/overview/pulls)\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-2-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)](https://github.com/ngneat/spectator)\n\n\u003e Overview - The Template for Success in Template Management\n\n## Compatibility with Angular Versions\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003e@ngneat/overview\u003c/th\u003e\n      \u003cth\u003eAngular\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n      \u003ctd\u003e\n        6.x\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003e= 17\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        5.x\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003e= 16\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        4.x\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003e= 14 \u003c 16\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        3.x\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003e= 13 \u003c 14\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        2.x\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003e= 11 \u003c 13\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Installation\n\n```bash\nnpm i @ngneat/overview\nyarn add @ngneat/overview\n```\n\n## Table of Contents\n\n- [DynamicView](#DynamicContent)\n- [Teleporting](#Teleporting)\n- [ViewService](#ViewService)\n  - [createView](#createView)\n  - [createComponent](#createComponent)\n  - [createTemplate](#createTemplate)\n\n## `DynamicView`\n\nUse the `dynamicView` structural directive to render a component, a template, HTML, or default template dynamically.\n\nLet’s say we build a generic error component. What we want is to give our consumers the flexibly to create it by using one of three options:\n\n- They can choose to use the default template\n- They can choose to use their own text which can be static or dynamic\n- They can choose to pass their own template or component\n\n```ts\nimport { DynamicViewDirective, Content } from '@ngneat/overview';\n\n@Component({\n  template: ` \u003cdiv *dynamicView=\"view\"\u003eDefault view\u003c/div\u003e `,\n  standalone: true,\n  imports: [DynamicViewDirective],\n})\nexport class ErrorComponent {\n  @Input() view: Content | undefined;\n}\n```\n\nYou can also pass a `context` or an [`injector`](https://angular.io/api/core/Injector) as `inputs` to the directive:\n\n```html\n\u003ch5\u003eComponent\u003c/h5\u003e\n\u003cng-container\n  *dynamicView=\"component; \n    injector: myInjector; \n    context: { $implicit: 'my title' }\"\n/\u003e\n\n\u003ch5\u003eTemplate\u003c/h5\u003e\n\u003cng-template #tpl let-title\u003e\n  \u003cb\u003e{{ title }}\u003c/b\u003e\n\u003c/ng-template\u003e\n\n\u003cng-container *dynamicView=\"tpl; context: { $implicit: 'my title' }\" /\u003e\n```\n\nIf you pass `context` to a component and the value can be accessed via the `injectViewContext` function:\n\n```ts\nimport { injectViewContext } from '@ngneat/overview';\n\ninterface Context {\n  title: string;\n}\n\n@Component({\n  template: `\u003cdiv\u003e{{ context().title }}\u003c/div\u003e`,\n  standalone: true,\n})\nexport class MyDynamicComponent {\n  context: Signal\u003cContext\u003e = injectViewContext\u003cContext\u003e();\n}\n```\n\n`injectViewContext` returns a readonly signal with the view's context object.\n\n## `Teleporting`\n\nTeleporting means rendering a view at a different location from its declaration. There are two cases it might be helpful:\n\n- Avoid prop drilling to a nested component.\n- Rendering a view at another place in the DOM while keeping its context where it’s defined.\n\nYou can read more about this approach in this [article](https://netbasal.com/beam-me-up-scotty-on-teleporting-templates-in-angular-a924f1a7798).\n\nUse the `teleportOutlet` directive to define a new `outlet`. An `outlet` is an anchor where the view will be projected as a sibling.\n\n```typescript\nimport { TeleportOutletDirective } from '@ngneat/overview';\n\n@Component({\n  template: `\n    \u003cdiv class=\"flex\"\u003e\n      \u003cng-container teleportOutlet=\"someId\"/\u003e\n    \u003c/div\u003e\n  `,\n  standalone: true,\n  imports: [TeleportOutletDirective],\n})\nexport class FooComponent {}\n```\n\nUse the `teleportTo` directive to `teleport` the view to a specific `outlet`:\n\n```typescript\nimport { TeleportDirective } from '@ngneat/overview';\n\n@Component({\n  template: `\n    \u003csection *teleportTo=\"someId\"\u003e\n      {{ value }}\n    \u003c/section\u003e\n  `,\n  standalone: true,\n  imports: [TeleportDirective],\n})\nexport class BarComponent {\n  value = '...';\n}\n```\n\n## ViewService\n\nThe `ViewService` provides `facade` methods to create modular views in Angular. It's been used in various projects like [hot-toast](https://github.com/ngneat/hot-toast), and [helipopper](https://github.com/ngneat/helipopper).\n\n### `createComponent`\n\nThe `createComponent` method takes a `Component`, and returns an instance of `CompRef`:\n\n```ts\nimport { ViewService, CompRef } from '@ngneat/overview';\n\n@Injectable()\nclass ToastService {\n  private viewService = inject(ViewService);\n  componentRef: CompRef;\n\n  init() {\n    this.componentRef = this.viewService\n      .createComponent(HotToastContainerComponent)\n      .setInput('defaultConfig', defaultConfig)\n      .appendTo(document.body);\n  }\n}\n```\n\nThere are cases where we want to use an Angular [component](https://netbasal.com/using-angular-components-with-third-party-libraries-522a1f33003) template in a third-party library that takes a native DOM element or a string. In this case, we can use the `getRawContent` or the `getElement` method, respectively.\n\n```ts\nimport { ViewService } from '@ngneat/overview';\n\n@Directive()\nclass ChartDirective {\n  private viewService = inject(ViewService);\n\n  createChart(color: string) {\n    const ref = this.viewService.createComponent(FooTooltip).setInput('color', color).detectChanges(document.body);\n\n    const content = ref.getRawContent();\n\n    ref.destroy();\n\n    Highcharts.chart('container', {\n      tooltip: {\n        formatter: function () {\n          return content;\n        },\n        useHTML: true,\n      },\n    });\n  }\n}\n```\n\n#### `createComponent` Options\n\n```ts\ncreateComponent\u003cComp, Context\u003e(component: Type\u003cComp\u003e, {\n  injector?: Injector,\n  environmentInjector?: EnvironmentInjector,\n  context?: Context,\n  vcr?: ViewContainerRef,\n})\n```\n\n### `createTemplate`\n\nThe `createTemplate` method takes a `TemplateRef`, and returns an instance of `ViewRef`.\n\n```ts\ncreateTemplate\u003cContext\u003e(tpl: TemplateRef\u003cContext\u003e, {\n  context?: Context,\n  vcr?: ViewContainerRef,\n  injector?: Injector,\n})\n```\n\n### `createView`\n\nThe `createView` method takes a `Component`, a `TemplateRef` or a `string`, and creates a `View`:\n\n```ts\nimport { ViewService, Content } from '@ngneat/overview';\n\n@Injectable()\nclass ToastService {\n  private viewService = inject(ViewService);\n\n  createToast(content: Content) {\n    const ref = this.viewService.createView(content);\n    document.body.appendChild(ref.getElement());\n  }\n}\n```\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://www.netbasal.com/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6745730?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eNetanel Basal\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/@ngneat/overview/commits?author=NetanelBasal\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#ideas-NetanelBasal\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/shhdharmen\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6831283?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDharmen Shah\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#content-shhdharmen\" title=\"Content\"\u003e🖋\u003c/a\u003e \u003ca href=\"https://github.com/@ngneat/overview/commits?author=shhdharmen\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n\n\u003cdiv\u003eIcons made by \u003ca href=\"http://www.freepik.com/\" title=\"Freepik\"\u003eFreepik\u003c/a\u003e from \u003ca href=\"https://www.flaticon.com/\" title=\"Flaticon\"\u003ewww.flaticon.com\u003c/a\u003e\u003c/div\u003e\n","funding_links":["https://github.com/sponsors/ngneat"],"categories":["Projects by main language","Third Party Components"],"sub_categories":["angular","Layout"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Foverview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngneat%2Foverview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngneat%2Foverview/lists"}