{"id":15024623,"url":"https://github.com/ciccio-90/fg-dynamic-component","last_synced_at":"2026-02-14T01:02:51.967Z","repository":{"id":226775260,"uuid":"769613978","full_name":"ciccio-90/fg-dynamic-component","owner":"ciccio-90","description":"Create an Angular standalone signals based dynamic components tree through a JSON configuration with full life-cycle support for inputs, outputs, attributes, reactive forms and expressions binding evaluation.","archived":false,"fork":false,"pushed_at":"2024-03-21T11:48:23.000Z","size":301,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-01T16:49:46.768Z","etag":null,"topics":["angular","angular2","component","dynamic","input","life-cycle","ng","output"],"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/ciccio-90.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2024-03-09T15:17:27.000Z","updated_at":"2024-07-05T13:59:35.000Z","dependencies_parsed_at":"2024-03-10T22:44:02.006Z","dependency_job_id":"9db34d11-95b3-4b53-90ab-7b5197a201b4","html_url":"https://github.com/ciccio-90/fg-dynamic-component","commit_stats":null,"previous_names":["ciccio-90/fg-dynamic-component"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ciccio-90/fg-dynamic-component","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciccio-90%2Ffg-dynamic-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciccio-90%2Ffg-dynamic-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciccio-90%2Ffg-dynamic-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciccio-90%2Ffg-dynamic-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ciccio-90","download_url":"https://codeload.github.com/ciccio-90/fg-dynamic-component/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciccio-90%2Ffg-dynamic-component/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29427632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T22:20:51.549Z","status":"ssl_error","status_checked_at":"2026-02-13T22:20:49.838Z","response_time":78,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","angular2","component","dynamic","input","life-cycle","ng","output"],"created_at":"2024-09-24T20:00:39.507Z","updated_at":"2026-02-14T01:02:51.922Z","avatar_url":"https://github.com/ciccio-90.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fg-dynamic-component\n\nCreate an Angular standalone signals based dynamic components tree through a JSON configuration with full life-cycle support for inputs, outputs, attributes, reactive forms and expressions binding evaluation.\n\n\u003cdetails\u003e\n  \u003csummary\u003eCompatibility with Angular\u003c/summary\u003e\n\n| Angular | fg-dynamic-component | NPM package                   |\n| ------- | -------------------- | ----------------------------- |\n| 17.2.4  | 1.1.1                | `fg-dynamic-component@^1.1.1` |\n| 17.2.4  | 1.1.0                | `fg-dynamic-component@^1.1.0` |\n| 17.2.4  | 1.0.2                | `fg-dynamic-component@^1.0.2` |\n| 17.2.4  | 1.0.1                | `fg-dynamic-component@^1.0.1` |\n\n\u003c/details\u003e\n\n## Installation\n\n```bash\n$ npm install fg-dynamic-component --save\n```\n\n## Usage\n\n### FGDynamicComponent\n\nImport `FGDynamicComponent` where you need to render dynamic components:\n\n```ts\nimport { FGDynamicComponent } from \"fg-dynamic-component\";\n\n@NgModule({\n    imports: [FGDynamicComponent]\n})\nexport class MyModule {}\n```\n\nThen in your component's template include `\u003cfg-dynamic\u003e` where you want to render component\nand bind from your component class type of component to render:\n\n```ts\nimport { FGDynamicService, FGDynamicItem } from \"fg-dynamic-component\";\n\nFGDynamicService.registerComponent(\"MyDynamicComponent1\", MyDynamicComponent1);\nFGDynamicService.registerComponent(\"MyDynamicComponent4\", import(\"...\").then(m =\u003e m.MyDynamicComponent4));\nFGDynamicService.registerComponent(\"MyDynamicComponent5\", async () =\u003e (await import(\"...\")).MyDynamicComponent5);\n\n@Component({\n    selector: \"my-component\",\n    template: `\u003cfg-dynamic [configuration]=\"configuration()\" /\u003e`\n})\nclass MyComponent {\n    configuration = signal({\n        type: \"MyDynamicComponent1\",\n        items: [\n            {\n                type: MyDynamicComponent2\n            },\n            {\n                type: import(\"...\").then(m =\u003e m.MyDynamicComponent3)\n            },\n            {\n                type: \"MyDynamicComponent4\"\n            },\n            {\n                type: \"MyDynamicComponent5\"\n            },\n            {\n                type: async () =\u003e (await import(\"...\")).MyDynamicComponent6\n            },\n            {\n                type: () =\u003e import(\"...\").then(m =\u003e m.MyDynamicComponent7)\n            }\n        ]\n    } as FGDynamicItem);\n}\n```\n\n#### Standalone API\n\nYou may use `\u003cfg-dynamic\u003e` as a standalone component:\n\n```ts\nimport { FGDynamicComponent, FGDynamicService, FGDynamicItem } from \"fg-dynamic-component\";\n\nFGDynamicService.registerComponent(\"MyDynamicComponent4\", import(\"...\").then(m =\u003e m.MyDynamicComponent4));\nFGDynamicService.registerComponent(\"MyDynamicComponent5\", async () =\u003e (await import(\"...\")).MyDynamicComponent5);\n\n@Component({\n    selector: \"my-component\",\n    template: `\u003cfg-dynamic [configuration]=\"configuration()\" /\u003e`,\n    imports: [FGDynamicComponent],\n    standalone: true\n})\nclass MyComponent {\n    configuration = signal({\n        items: [\n            {\n                type: MyDynamicComponent2\n            },\n            {\n                type: import(\"...\").then(m =\u003e m.MyDynamicComponent3)\n            },\n            {\n                type: \"MyDynamicComponent4\"\n            },\n            {\n                type: \"MyDynamicComponent5\"\n            },\n            {\n                type: async () =\u003e (await import(\"...\")).MyDynamicComponent6\n            },\n            {\n                type: () =\u003e import(\"...\").then(m =\u003e m.MyDynamicComponent7)\n            }\n        ]\n    } as FGDynamicItem);\n}\n```\n\n_NOTE:_ You can declare components to dynamically load in static and/or dynamic way using or not the FGDynamicService.\n\n### Inputs and Outputs\n\nYou can pass `inputs` and `outputs` to your dynamic components:\n\n```ts\n@Component({\n    selector: \"my-component\",\n    template: `\u003cfg-dynamic [configuration]=\"configuration()\" /\u003e`,\n    imports: [FGDynamicComponent],\n    standalone: true\n})\nclass MyComponent {\n    configuration = signal({\n        type: MyDynamicComponent1,\n        inputs: {\n            hello: \"world\",\n            something: () =\u003e \"can be really complex\"\n        },\n        outputs: {\n            onSomething: (type) =\u003e alert(type)\n        }\n    } as FGDynamicItem);\n}\n\n@Component({\n    selector: \"my-dynamic-component1\",\n    template: \"Dynamic Component 1\"\n})\nclass MyDynamicComponent1 {\n    @Input()\n    hello: string;\n    @Input()\n    something: Function;\n    @Output()\n    onSomething = new EventEmitter\u003cstring\u003e();\n}\n```\n\nYou can update your inputs passing expressions binding using a view model and they will trigger standard Angular's life-cycle hooks\n(of course you should consider which change detection strategy you are using).\n\n```ts\n@Component({\n  selector: 'my-component',\n  template: `\u003cfg-dynamic [configuration]=\"configuration()\" [(viewModel)]=\"viewModel\" /\u003e`,\n  imports: [FGDynamicComponent],\n  standalone: true\n})\nclass MyComponent {\n  configuration = signal({\n    type: MyDynamicComponent1,\n    inputs: {\n        hello: '$vm().count % 2 === 0 ? $vm().message : \\'Hello World!\\''\n    },\n    outputs: {\n        onSomething: '$vm.update(viewModel =\u003e { ...viewModel, message: $event, count: viewModel.count + 1 })'\n    }\n  } as FGDynamicItem);\n  viewModel = model({ message: 'Hello World!', count: 0  });\n}\n\n@Component({\n  selector: 'my-dynamic-component1',\n  template: 'Dynamic Component 1'\n})\nclass MyDynamicComponent1 {\n  @Input()\n  hello: string;\n  @Input()\n  something: Function;\n  @Output()\n  onSomething = new EventEmitter\u003cstring\u003e();\n}\n```\n\n### Attributes\n\nYou can declaratively set attributes, as you would inputs.\n\n```ts\n@Component({\n    selector: \"my-component\",\n    template: `\u003cfg-dynamic [configuration]=\"configuration()\" [(viewModel)]=\"viewModel\" /\u003e`\n})\nclass MyComponent {\n    configuration = signal({\n        type: MyDynamicComponent1,\n        attributes: {\n            \"my-attribute\": \"attribute-value\",\n            class: \"some classes\",\n            disabled: \"$vm().isDisabled\"\n        }\n    } as FGDynamicItem);\n    viewModel = model({ isDisabled: true });\n}\n```\n\n### Reactive Forms\n\nYou can declaratively set attributes to activate model binding, form control status (enabled/disabled) and validations with your ControlValueAccessor components.\n\n\u003e **Attributes**:\n\u003e\n\u003e-   name: used to attach the new control to the input form group (must match the view model property name).\n\u003e-   disabled: specifies that an input field should be disabled.\n\u003e-   maxlength: specifies the maximum number of characters allowed in an input field.\n\u003e-   minlength: specifies the minimum number of characters allowed in an input field.\n\u003e-   min: specifies the minimum value for an input field.\n\u003e-   max: specifies the maximum value for an input field.\n\u003e-   pattern: specifies a regular expression that the input field's value is checked against.\n\u003e-   required: specifies that an input field must be filled.\n\u003e-   email: defines a field automatically validated to ensure it is a properly formatted e-mail address.\n\n```ts\n@Component({\n    selector: \"my-component\",\n    template: `\u003cfg-dynamic [configuration]=\"configuration()\" [(viewModel)]=\"viewModel\" [formGroup]=\"formGroup()\" /\u003e`\n})\nclass MyComponent {\n    configuration = signal({\n        type: MyDynamicComponent1,\n        attributes: {\n            name: \"data.firstName\",\n            disabled: \"$vm().metadata.firstName.disabled\",\n            maxlength: 20,\n            required: true\n        }\n    } as FGDynamicItem);\n    viewModel = model({ data: { firstName: \"Jhon\" }, metadata: { firstName: { disabled: false } } });\n    formGroup = signal(new FormGroup({}));\n}\n```\n\n## Contributing\n\nYou are welcome to contribute to this project.\nSimply follow the [contribution guide](/CONTRIBUTING.md).\n\n## License\n\nMIT © [Francesco Guagnano](guagnanofrancesco11@gmail.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciccio-90%2Ffg-dynamic-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fciccio-90%2Ffg-dynamic-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciccio-90%2Ffg-dynamic-component/lists"}