{"_id":"@codexio/ngx-reactive-forms-generator","_rev":"7-1b93b6a5deb14b5d9909e3d9be13d377","name":"@codexio/ngx-reactive-forms-generator","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"@codexio/ngx-reactive-forms-generator","version":"1.0.0","description":"Creates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"prepublish":"tsc","build":"tsc","test":"echo \"Error: no test specified\" && exit 1"},"keywords":["reactive","forms","formgroup","angular","dto","decorators","dynamic","formgroup"],"author":{"name":"Ivan Yonkov"},"license":"ISC","dependencies":{"@angular/forms":"^15.1.2"},"gitHead":"a317db8253092453e8a249237e0d15d36e341480","_id":"@codexio/ngx-reactive-forms-generator@1.0.0","_nodeVersion":"16.15.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-dHhI0L325Fw8tE+rui3tf/6cYtG9xTtqQb9nU2Y9aRN/xvrzgzaVMNMb810IicGVti6pAHzJjngS2ZVs1FPSDQ==","shasum":"6d3bdb849fd4044ca569422aa82048083c9c1957","tarball":"https://registry.npmjs.org/@codexio/ngx-reactive-forms-generator/-/ngx-reactive-forms-generator-1.0.0.tgz","fileCount":6,"unpackedSize":56901,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBkfJPnF5KrPPXOD3Ai5GZLnlwa5ehuwKgKPaM/D/nhVAiEAjaUUa5uhgBWmd85Gpmc5ouaibWV7bCLqluZ2AmDiSoA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj1l0nACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr3PA//c28h2qdbN1rIL7UgrXQtneFqeLx3x1mjjvZ3u4G1KuWZQAj8\r\nTqQuMEj8Uq4OrId3WccD2sb0EkL9lgMpRIlFd9NN2wWv0b3TlsNhSLXiIpg/\r\nklhrBLozieMKNP66jOoNdJCLlH35cKbTIgtU8REudDKYYO4bJeKb6jVTRtlm\r\nMLa12TQ64DT0yzc0+TMLDPt5f71xQdhVcMFy0ceSe4GkgFUorQ4pMqtEH8EI\r\nCc6NkcRlyuHw21RyIMYr6iKym/VEUaq5Tvw+1lXZhHBO1kJJYw7UnaG3ooIb\r\nxqVVoT7hB69aeo2qf8fp0pNU/yLNy3RcGV1GI4rAbdFUyKfL6I0Q7knB0hQr\r\ngqtCJ7ScpMw7q2h7bzVZlsMZUODlqr6RKA1E87Ne6wjGiY1ZCOZur/2QIMbi\r\ntMPA9VhX5pRkjw8oS13j5flW75Dc26KLUvp22RuGscb5zYKZSnzYNThyfnhl\r\nKAPngZfcx2zAcKZ0LozJZuZsXj1ZmuutPhlMfi7omZGDfvS0CNU7bBymOCUO\r\nojxQduC8M/Pm1brV8xUYCIBcDvakDiKtK2rVUsAuNA6d0r3zVSF214RgUJwU\r\nJ9ZJzXtjdiIL28forFISCpMNU0fktzM32nkPvgzwYWxYJXDSXls2Muz00TX0\r\nO35zHJICYyZGGAYUNY87Oz0LlnwVHs2Qm9I=\r\n=aEc1\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"royalbg","email":"ivan.yonkov@codexio.bg"},"directories":{},"maintainers":[{"name":"iludart","email":"peter.penev@hotmail.com"},{"name":"vonrepiks","email":"hristo.skipernov@codexio.bg"},{"name":"royalbg","email":"ivan.yonkov@codexio.bg"},{"name":"chrispam","email":"chrispam1509@gmail.com"},{"name":"georgi_locktrip","email":"georgi.georgiev@locktrip.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ngx-reactive-forms-generator_1.0.0_1674992935281_0.03029457631092569"},"_hasShrinkwrap":false},"1.0.1":{"name":"@codexio/ngx-reactive-forms-generator","version":"1.0.1","description":"Creates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"prepublish":"tsc","build":"tsc","test":"echo \"Error: no test specified\" && exit 1"},"keywords":["reactive","forms","formgroup","angular","dto","decorators","dynamic","formgroup"],"author":{"name":"Ivan Yonkov"},"license":"ISC","dependencies":{"@angular/forms":"^15.1.2"},"repository":{"type":"git","url":"git+https://github.com/CodexioLtd/ngx-reactive-forms-generator.git"},"gitHead":"6354d9a5d2d10b4b6249c776216a589a7e1b49cc","bugs":{"url":"https://github.com/CodexioLtd/ngx-reactive-forms-generator/issues"},"homepage":"https://github.com/CodexioLtd/ngx-reactive-forms-generator#readme","_id":"@codexio/ngx-reactive-forms-generator@1.0.1","_nodeVersion":"16.15.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-J1PohS5b4rL4NsE9rg7pNLbXYfSAgQHZ50V8uffw35sk475S49hyRqVaIBSyPfI1sxqr594UZAr002qNVV5kZQ==","shasum":"9ee208e02c79f1ad26c9411cc99df2214421f8cf","tarball":"https://registry.npmjs.org/@codexio/ngx-reactive-forms-generator/-/ngx-reactive-forms-generator-1.0.1.tgz","fileCount":6,"unpackedSize":57015,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBY689fvUAPz8Xo6ZvGwftYoUEOAKL+z7pKHVjHtudHqAiEA1y2DGzcNzXCZL2KTK0KBnavEjsq2aJRZ7OWh0bezyfQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj1l3RACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpoFg/+PziURoqljestxQkoG7oFCvUGGAYax1w2xehANqKgGpUD/0Sj\r\nl8Cg6n0dgP/CEYGxS6jtQgIyeWVn7CwP/DyHuQSu8E6m4NpK4m2wMYYkQkWK\r\nkL+gZyd+bEyN6sqca5KwvZ9HUJQlWqcnZnL60r+qFTULxoqhWarNt3AHGfXN\r\nmg5h/8EmQiRiKRNAMzeOKPy5Qtj/tSRkZt3uYdIrmAyA7YnYhvRzLjS2Mfkn\r\ncrMB3W4K+9617OBlOEJ91kb5676UYwDSQDzLbLFc8Igd+n74Mgg44qFienI4\r\nQZhjVHO8liXO5PXP7GrgmKS5pnaFBRorYMb+Ua5rNSNQJ1j/ZSYK+MDtXArU\r\n23XLk8CIhsHzU+Ix/3sYQ/JmXZAvDcxSct1ON4do55YLoL/uhbIUUAJx0ghs\r\nP4OsQbRD+7f/9E+3sl4u/jxC0EIg6r7KckyUwPZr01kneCBfkVKkvikZ3n6y\r\nTYZa9r0BUIRa4kMGI/gfKT5P33Jz5GyxUxgudTh4AKfOrKoVX6yYF4YaIN6E\r\nyWPgvkSEmclYKYITWmIbp37Q125NUW3BcNROo2hzcV1Q2joEX/hR5iFirYKI\r\nN/UCDxRDp06YNTkfHWZbpZS9SVtteqXJzI6cHuVeD+Fa6Mn4umzLj7QO1Go+\r\nlDXI7cbHepHZ22yBbHwLunV687gXsz04X1Y=\r\n=UedY\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"royalbg","email":"ivan.yonkov@codexio.bg"},"directories":{},"maintainers":[{"name":"royalbg","email":"ivan.yonkov@codexio.bg"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ngx-reactive-forms-generator_1.0.1_1674993104887_0.6081305584402177"},"_hasShrinkwrap":false},"1.0.2":{"name":"@codexio/ngx-reactive-forms-generator","version":"1.0.2","description":"Creates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"prepublish":"npm run build && npm run test","build":"tsc","test":"tsc && node--test dist/tests.js"},"keywords":["reactive","forms","formgroup","angular","dto","decorators","dynamic","formgroup"],"author":{"name":"Ivan Yonkov"},"license":"ISC","dependencies":{"@angular/forms":"^15.1.2"},"devDependencies":{"test":"^3.2.1","@angular/compiler":"^15.1.2","@types/node":"^18.11.18","@angular/core":"^15.1.2","rxjs":"^7.8.0"},"repository":{"type":"git","url":"git+https://github.com/CodexioLtd/ngx-reactive-forms-generator.git"},"type":"module","gitHead":"cc5027f0fb357f83fd245ad1c3d74e2321b8038f","bugs":{"url":"https://github.com/CodexioLtd/ngx-reactive-forms-generator/issues"},"homepage":"https://github.com/CodexioLtd/ngx-reactive-forms-generator#readme","_id":"@codexio/ngx-reactive-forms-generator@1.0.2","_nodeVersion":"16.15.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-Mb+AZezsmUenbz6Nuhsjhjt6jA+ca/uYBe7bEXCD1LL9VQQCBs7nWFVhLvtofXBQkQS/NwW+NM5FuP/kJAbjXA==","shasum":"c57f24e36f7439a53f612e33178d29f57edc1114","tarball":"https://registry.npmjs.org/@codexio/ngx-reactive-forms-generator/-/ngx-reactive-forms-generator-1.0.2.tgz","fileCount":20,"unpackedSize":109078,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDn4SSQjSoa6ZgkC2GTXJprdbevJzFZnY0qFjpM9jkpQAiEA8QujL6Mp+Tmoq5BR/D4sNQ5zadWCZ/JltUOLZAm7xcs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj1tcbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrnAA//Zc1bFUTJlXcD8LpjMZ/n+Fo+VRv6ihgrS7PRHLGN+2GW1+Kv\r\nuhzaE2mSqUY/CxuB0WsECbv1tbHcdBOxnZy3rvJU1Kv/Bb7+XIQmdgTH3kJ5\r\nUc2F4jOUy2cAehE3C1yGYPkq/3TZJrfbAGhyyCEYfTBncPVvavswKVdLM7P1\r\nn1auKXnPNlDzirqCZJ+mePfut+aeKBfrcfSod07z/X9sIgl4bAsCJB8O5hDM\r\npg9Helr0RBGqDFuzvVv6TxvCI4sR1rebv3DvMB4YBnU8hHbWFL2Rhjtsrl+X\r\n5YI7kx/uzH+h6A7TpTWz9EWfeT2W+ANq2bxrLNx/ileTdMpn4qk3wfsj2JNs\r\nSVn2TYscg4GwVbe3AQMDXMq7N5B9Y6HFPASwgJxR9HFZd+ROnDaAWSW3SPs+\r\nbUEg+5CDwilOHym7mskxO2bEaDuTv/SsJg7thYwAaAHdIzUkkeZp8Bxr5AI/\r\nbKApDtsClCF8vTW9Sf2IpTUd9EFH/cBZVOHbDw3gV+LeXoRFwBoCFNpeHvED\r\nCP/isMiyk7ABLCq+gILRIwNbUO5Oo14Hqo05IyU4Ah5Kd+0eBnaamIdvO8oj\r\nRGOupCbnZCvBsnW84qqTs77SrkQdpercrfNlUL/ZaYQOUjNMgPVUyM0Cqc0f\r\nvWMGV8v+gMKgDrEd2fzmWojo+fB98gSTXK0=\r\n=mrvf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"royalbg","email":"ivan.yonkov@codexio.bg"},"directories":{},"maintainers":[{"name":"royalbg","email":"ivan.yonkov@codexio.bg"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ngx-reactive-forms-generator_1.0.2_1675024155577_0.05739599973211007"},"_hasShrinkwrap":false},"1.0.3":{"name":"@codexio/ngx-reactive-forms-generator","version":"1.0.3","description":"Creates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"prepublish":"npm run build && npm run test","build":"tsc","test":"tsc && node--test dist/tests.js"},"keywords":["reactive","forms","formgroup","angular","dto","decorators","dynamic","formgroup"],"author":{"name":"Ivan Yonkov"},"license":"ISC","dependencies":{"@angular/forms":"^16.0.0"},"devDependencies":{"typescript":"^5.1.3","test":"^3.2.1","@angular/compiler":"^16.0.0","@types/node":"^20.3.0","@angular/core":"^16.0.0","rxjs":"^7.8.1"},"repository":{"type":"git","url":"git+https://github.com/CodexioLtd/ngx-reactive-forms-generator.git"},"type":"module","gitHead":"a4811db1d50f5dfb25079793612008e405848dde","bugs":{"url":"https://github.com/CodexioLtd/ngx-reactive-forms-generator/issues"},"homepage":"https://github.com/CodexioLtd/ngx-reactive-forms-generator#readme","_id":"@codexio/ngx-reactive-forms-generator@1.0.3","_nodeVersion":"19.8.1","_npmVersion":"9.5.1","dist":{"integrity":"sha512-/7fg1GPMbEHRVFfcFj3yKbEz11kWIl9wfT8sS/4/cR7Ixgvg/vvT7P97uscjVMoZVP8I3fH3Z3bHJAfgQG1EBg==","shasum":"871877e9a0a854bbacd5093dccc7017188d272da","tarball":"https://registry.npmjs.org/@codexio/ngx-reactive-forms-generator/-/ngx-reactive-forms-generator-1.0.3.tgz","fileCount":18,"unpackedSize":108791,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5UrMExIY1sGLKdqNRFgaeTpn3BqEIbsgRMlldnj2EhwIhAK5qZgu3cwU+3ig3ULG9OSvM+lwckA2kWDJUnFQp92j1"}]},"_npmUser":{"name":"royalbg","email":"ivan.yonkov@codexio.bg"},"directories":{},"maintainers":[{"name":"royalbg","email":"ivan.yonkov@codexio.bg"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ngx-reactive-forms-generator_1.0.3_1686577503027_0.827574080485832"},"_hasShrinkwrap":false}},"time":{"created":"2023-01-29T11:48:55.234Z","1.0.0":"2023-01-29T11:48:55.457Z","modified":"2023-06-12T13:45:03.610Z","1.0.1":"2023-01-29T11:51:45.068Z","1.0.2":"2023-01-29T20:29:15.783Z","1.0.3":"2023-06-12T13:45:03.499Z"},"maintainers":[{"name":"royalbg","email":"ivan.yonkov@codexio.bg"}],"description":"Creates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators","keywords":["reactive","forms","formgroup","angular","dto","decorators","dynamic","formgroup"],"author":{"name":"Ivan Yonkov"},"license":"ISC","readme":"# ngx-reactive-forms-generator\nCreates Angular FormGroup instances from DTOs (e.g. class PersonRequest) using decorators\n\n<a href=\"https://www.npmjs.com/package/@codexio/ngx-reactive-forms-generator\" target=\"_blank\"><img src=\"https://img.shields.io/npm/v/@codexio/ngx-reactive-forms-generator.svg\" alt=\"NPM Version\" /></a>\n<a href=\"https://www.npmjs.com/package/@codexio/ngx-reactive-forms-generator\" target=\"_blank\"><img src=\"https://img.shields.io/npm/l/@codexio/ngx-reactive-forms-generator.svg\" alt=\"Package License\" /></a>\n<a href=\"https://www.npmjs.com/package/@codexio/ngx-reactive-forms-generator\" target=\"_blank\"><img src=\"https://img.shields.io/npm/dm/@codexio/ngx-reactive-forms-generator.svg\" alt=\"NPM Downloads\" /></a>\n\n# Table of Contents\n- [Preambule](#preambule)\n- [API Docs with Examples](#api-docs-with-examples)\n  * [Decorator `@FormGroupTarget`](#decorator-formgrouptarget)\n  * [Decorator `@FormGroupValidators`](#decorator-formgroupvalidators)\n  * [Decorator `@FormGroupAsyncValidators`](#decorator-formgroupasyncvalidators)\n  * [Decorator `@FormControlTarget`](#decorator-formcontroltarget)\n  * [Decorator `@FormControlAsyncValidators`](#decorator-formcontrolasyncvalidators)\n  * [Decorator `@NestedFormGroup`](#decorator-nestedformgroup)\n  * [Function `toFormGroup<Type>(Type, [FormIdType])`](#function-toformgrouptypetype-formidtype)\n  * [Function `toFormGroups<Type>(Type, FormIdType[])`](#function-toformgroupstypetype-formidtype)\n- [Installation](#installation)\n  * [Installation / Usage Example](#installation--usage-example)\n\n# Preambule[^](#table-of-contents \"Table of Contents\")\nHave you felt the burden of describing your models in classes/interfaces and then redescribing them as `FormGroup` objects with multiple `FormControl` nested children? All the boilerplate that you need to write in order to achieve a decent **Reactive Forms** foundation in your project? It's not the case anymore!\n\nWith several TypeScript decorators called `@FormGroupTarget`, `@FormGroupValidators`, `@FormGroupAsyncValidators`, `@FormControlTarget`, `@FormControlAsyncValidators` and `@NestedFormGroup` you can have a Reactive Form right out of your DTO.\n\nForget having this repetition and boilerplate:\n\n```ts\ninterface LoginForm {\n  email: FormControl<string>;\n  password?: FormControl<string>;\n}\n\nconst loginFormGroup = new FormGroup<LoginForm>({\n  email: new FormControl('', {nonNullable: true}),\n  password: new FormControl('', Validators.minLength(6)),\n});\n```\n\nBut instead welcome:\n\n```ts\nclass LoginForm {\n  @FormControlTarget({nonNullable: true})\n  email: string;\n  \n  @FormControlTarget(Validators.minLength(6))\n  password: string;\n}\n\nconst loginFormGroup = toFormGroup<LoginForm>(LoginForm)!;\n```\n\n# API Docs with Examples[^](#table-of-contents \"Table of Contents\")\n\n## Decorator `@FormGroupTarget`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a class to denote that\nthis class will be a target type if a form group value.\n\nIf your class will be a target of multiple forms,\nwhich have different options, validators, and\nmaybe subset of fields, you can use this decorator\nmultiple times, denoting a unique identifier called\n**formId**. Then each validator and form control which\nis participating in the particular form group should\nshare the same **formId**\n\nUsage:\n```ts\n@FormGroupTarget()\n@FormGroupTarget(\"editForm\")\nclass InvoiceRequest {\n\n}\n```\n\n## Decorator `@FormGroupValidators`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a class to denote that\nthis class, which is already a target of\na form group (**@FormGroupTarget**)\nwill have synchronous validators.\n\nIn order to add different validators to\ndifferent form groups of the same type,\nan additional parameter **formId**\nshould be supplied\n\nExample:\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\nclass InvoiceRequest {\n\n}\n```\n\nIf two or more forms share the same validators,\nan array of **formId** could be supplied,\nso they will reflect in all of them.\nIf you do not name your default form group, a formId will\nbe assigned from the library. In order to access it later\n(e.g. in the **formId** array) use the\n**DEFAULT_GROUP** constant.\n\nExample:\n```ts\n@FormGroupTarget()\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators([Validators.email, Validators.requiredTrue], [DEFAULT_GROUP, \"editForm\"])\nclass InvoiceRequest {\n\n}\n    \n```\n\n## Decorator `@FormGroupAsyncValidators`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a class to denote that\nthis class, which is already a target of\na form group (**@FormGroupTarget**)\nwill have asynchronous validators.\n\nIn order to add different validators to\ndifferent form groups of the same type,\nan additional parameter **formId**\nshould be supplied\n\nExample:\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n}\n```\n\nIf two or more forms share the same validators,\nan array of **formId** could be supplied,\nso they will reflect in all of them.\nIf you do not name your default form group, a formId will\nbe assigned from the library. In order to access it later\n(e.g. in the **formId** array) use the\n**DEFAULT_GROUP** constant.\n\nExample:\n```ts\n@FormGroupTarget()\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators([Validators.email, Validators.requiredTrue], [DEFAULT_GROUP, \"editForm\"])\n@FormGroupAsyncValidators([ctrl => of({ value: ctrl.value}), ctrl => of({ empty: !ctrl.value})], [DEFAULT_GROUP, \"editForm\"])\nclass InvoiceRequest {\n\n}\n```\n\n## Decorator `@FormControlTarget`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a **field/property** or a\nconstructor **parameter** to denote that\nthis property is a **FormControl**\n\nSame as `@FormGroupValidators` it can be associated\nto a particular form group by supplying **formId**.\n\nThis decorator also accepts as an argument on or more\n`Validators` or `FormControlOptions` (optionally).\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n  @FormControlTarget(Validators.required)\n  @FormControlTarget(Validators.minLength(3), \"editForm\")\n  public num: string = '001';\n\n  constructor(\n      @FormControlTarget([], \"editForm\")\n      public date: Date = new Date()\n  ) { }\n}\n```\n\n If a form control shares the same settings on two or more\n form groups, an array of **formId** can be supplied\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n  @FormControlTarget([Validators.required, Validators.minLength(3)], [DEFAULT_GROUP, \"editForm\"])\n  public num: string = '001';\n\n  constructor(\n      @FormControlTarget([], [DEFAULT_GROUP, \"editForm\"])\n      public date: Date = new Date()\n  ) { }\n}\n```\n\n## Decorator `@FormControlAsyncValidators`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a **field/property** or a\nconstructor **parameter** to denote that\nthis form control has asynchronous validators.\n\nSame as `@FormGroupValidators` it can be associated\nto a particular form group by supplying **formId**.\n\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n  @FormControlTarget(Validators.required)\n  @FormControlTarget(Validators.minLength(3), \"editForm\")\n  @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n  @FormControlAsyncValidators(ctrl => of({ notOk: ctrl.state != 'VALID'}), \"editForm\")\n  public num: string = '001';\n\n  constructor(\n      @FormControlTarget([], \"editForm\")\n      @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n      public date: Date = new Date()\n  ) { }\n}\n```\n\n If a form control shares the same async validators on two or more\n form groups, an array of **formId** can be supplied\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n  @FormControlTarget([Validators.required, Validators.minLength(3)], [DEFAULT_GROUP, \"editForm\"])\n  @FormControlAsyncValidators([ctrl => of({ ok: ctrl.state == 'VALID'}), ctrl => of({ notOk: ctrl.state != 'VALID'})], [DEFAULT_GROUP, \"editForm\"])\n  public num: string = '001';\n\n  constructor(\n      @FormControlTarget([], [DEFAULT_GROUP, \"editForm\"])\n      @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}), [DEFAULT_GROUP, \"editForm\"])\n      public date: Date = new Date()\n  ) { }\n}\n```\n\n## Decorator `@NestedFormGroup`[^](#table-of-contents \"Table of Contents\")\n\nDecorator used on a **field/property** or a\nconstructor **parameter** to denote that\nthis form control is actually a previously defined form group,\nin other words - a nested form group.\n\nThis is the equivalent of:\n\n```ts\nconst topLevelFormGroup = new FormGroup({\n fieldOne: new FormControl(...),\n nestedFormGroup: new FormGroup({  // <---- this \n     nestedFieldInNestedGroup: new FormControl(...)\n })\n});\n```\n\nSame as `FormGroupValidators` it can be associated\nto a particular form group by supplied `targetFormId`\n\nAlso, since the nested entity may define more than one form group\nas described the nature of the decorators above, the second parameter\n**sourceFormId** actually chooses which of them to nest.\n\n\nExample (Basic):\n\n```ts\n@FormGroupTarget()\nclass SupplierRequest {\n\n @FormControlTarget()\n public name: string = '';\n\n @FormControlTarget()\n public address: string = '';\n}\n\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n@FormControlTarget(Validators.required)\n@FormControlTarget(Validators.minLength(3), \"editForm\")\n@FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n@FormControlAsyncValidators(ctrl => of({ notOk: ctrl.state != 'VALID'}), \"editForm\")\npublic num: string = '001';\n\nconstructor(\n   @FormControlTarget([], \"editForm\")\n   @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n   public date: Date = new Date(),\n\n   @NestedFormGroup(SupplierRequest)\n   public supplier: SupplierRequest = new SupplierRequest()\n) { }\n}\n```\n\nIf the nested form group (the `SupplierRequest`) defines more than\none form group, we can choose which one of them to nest.\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupTarget(\"validatedSupplier\")\nclass SupplierRequest {\n\n @FormControlTarget()\n @FormControlTarget(Validators.required, \"validatedSupplier\")\n public name: string = '';\n\n @FormControlTarget()\n @FormControlTarget(Validators.required, \"validatedSupplier\")\n public address: string = '';\n}\n\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n@FormControlTarget(Validators.required)\n@FormControlTarget(Validators.minLength(3), \"editForm\")\n@FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n@FormControlAsyncValidators(ctrl => of({ notOk: ctrl.state != 'VALID'}), \"editForm\")\npublic num: string = '001';\n\nconstructor(\n   @FormControlTarget([], \"editForm\")\n   @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n   public date: Date = new Date(),\n\n   @NestedFormGroup(SupplierRequest, \"validatedSupplier\")\n   public supplier: SupplierRequest = new SupplierRequest()\n) { }\n}\n```\n\nIn the previous example we have nested the **validatedSupplier**\nform group to the default form group of **InvoiceRequest**. We can choose to nest it\nto **editForm** or to all of them\n\nExample:\n\n```ts\n@FormGroupTarget()\n@FormGroupTarget(\"validatedSupplier\")\nclass SupplierRequest {\n\n @FormControlTarget()\n @FormControlTarget(Validators.required, \"validatedSupplier\")\n public name: string = '';\n\n @FormControlTarget()\n @FormControlTarget(Validators.required, \"validatedSupplier\")\n public address: string = '';\n}\n\n@FormGroupTarget()\n@FormGroupValidators(Validators.email)\n@FormGroupAsyncValidators(ctrl => of({ value: ctrl.value}))\n\n@FormGroupTarget(\"editForm\")\n@FormGroupValidators(Validators.requiredTrue, \"editForm\")\n@FormGroupAsyncValidators(ctrl => of({ empty: !ctrl.value}))\nclass InvoiceRequest {\n\n@FormControlTarget(Validators.required)\n@FormControlTarget(Validators.minLength(3), \"editForm\")\n@FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n@FormControlAsyncValidators(ctrl => of({ notOk: ctrl.state != 'VALID'}), \"editForm\")\npublic num: string = '001';\n\nconstructor(\n   @FormControlTarget([], \"editForm\")\n   @FormControlAsyncValidators(ctrl => of({ ok: ctrl.state == 'VALID'}))\n   public date: Date = new Date(),\n\n   @NestedFormGroup(SupplierRequest, \"validatedSupplier\", [DEFAULT_GROUP, \"editForm\"])\n   public supplier: SupplierRequest = new SupplierRequest()\n) { }\n}\n```\n\n## Function `toFormGroup<Type>(Type, [FormIdType])`[^](#table-of-contents \"Table of Contents\")\n\nThis function returns a FormGroup (in particular an\nenhanced **ModelFormGroup** which **value<**\nproperty will be of a generic type supplied) based on the decorators\nupon a class.\n\nExample:\n\n```ts\nngOnInit(): void {\n    const formGroup = toFormGroup<InvoiceRequest>(InvoiceRequest);\n    const invoice: InvoiceRequest = formGroup.value!;\n}\n```\n\nIt accepts an optional second parameter **formId** if you want to retrieve a particular (non-default) form.\n\nExample\n\n```ts\nngOnInit(): void {\n    const defaultFormGroup = toFormGroup<InvoiceRequest>(InvoiceRequest);\n    const defaultInvoice: InvoiceRequest = defaultFormGroup.value!;\n    \n    const editFormGroup = toFormGroup<InvoiceRequest>(InvoiceRequest, \"editForm\");\n    const editInvoice: InvoiceRequest = editFormGroup.value!;\n}\n```\n\n## Function `toFormGroups<Type>(Type, FormIdType[])`[^](#table-of-contents \"Table of Contents\")\n\nSame as `toFromGroup`, but gives an array of form groups associated to this `Type` depending on the array of *formId* supplied.\nIf empty array is supplied, it will return all form groups associated to the given `Type`\n\nExample:\n\n```ts\nngOnInit(): void {\n    const allFormGroupsImplicit = toFormGroups<InvoiceRequest>(InvoiceRequest);\n    allFormGroupsImplicit.forEach(invoiceFormGroup => {\n        const invoice: InvoiceRequest = invoiceFormGroup.value!;\n    });\n    \n    const allFormGroupsExplicit = toFormGroups<InvoiceRequest>(InvoiceRequest, [DEFAULT_GROUP, \"editForm\"]);\n    allFormGroupsExplicit.forEach(invoiceFormGroup => {\n        const invoice: InvoiceRequest = invoiceFormGroup.value!;\n    });\n}\n```\n\n# Installation[^](#table-of-contents \"Table of Contents\")\n\nInstallation is very simple. You just need to install the `npm` package `@codexio/ngx-reactive-forms-generator` into your Angular project. Then all the above decorators and functions will be available to be imported across your project\n\n## Installation / Usage Example[^](#table-of-contents \"Table of Contents\")\n\n**Terminal**\n```shell\n$ npm i @codexio/ngx-reactive-forms-generator\n```\n\n**app.component.ts**\n```ts\nimport {FormControlTarget, ModelFormGroup, toFormGroup} from \"@codexio/ngx-reactive-forms-generator\";\n\nimport {Component} from '@angular/core';\nimport {Validators} from \"@angular/forms\";\n\nclass LoginForm {\n  @FormControlTarget({updateOn: 'submit', validators: Validators.required})\n  email: string = '';\n\n  @FormControlTarget(Validators.minLength(6))\n  password: string = '';\n}\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html'\n})\nexport class AppComponent implements OnInit {\n\n  loginForm: ModelFormGroup<LoginForm> = toFormGroup<LoginForm>(LoginForm)!;\n\n  login() {\n    console.log(this.loginForm);\n    console.log(this.loginForm.value); // LoginForm object\n  }\n  \n}\n```\n\n**app.component.html** *(Not related to this library, it uses standard Reactive Forms notations)*:\n\n```html\n<h1>Login</h1>\n<form [formGroup]=\"loginForm\" (ngSubmit)=\"login()\">\n  <input type=\"text\" formControlName=\"email\" /><br/>\n  <div *ngIf=\"loginForm.get('email')?.errors?.['required'] && loginForm.get('email')?.dirty\">\n    Email is required <!-- Will appear after submit -->\n  </div>\n\n  <input type=\"password\" formControlName=\"password\" /><br/>\n  <div *ngIf=\"loginForm.get('password')?.errors?.['minlength'] && loginForm.get('password')?.dirty\">\n    Password too short <!-- Will appear when you change the value and it's with length < 6 -->\n  </div>\n\n  <button type=\"submit\">Login</button>\n</form>\n```\n\nEnjoy :)\n","readmeFilename":"README.md","homepage":"https://github.com/CodexioLtd/ngx-reactive-forms-generator#readme","repository":{"type":"git","url":"git+https://github.com/CodexioLtd/ngx-reactive-forms-generator.git"},"bugs":{"url":"https://github.com/CodexioLtd/ngx-reactive-forms-generator/issues"}}