{"id":19893065,"url":"https://github.com/iliaidakiev/form-control-change-tracker","last_synced_at":"2025-05-02T19:30:38.650Z","repository":{"id":37905803,"uuid":"264209944","full_name":"IliaIdakiev/form-control-change-tracker","owner":"IliaIdakiev","description":"Angular Form Control Change Tracker","archived":false,"fork":false,"pushed_at":"2023-02-03T08:16:49.000Z","size":520,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-25T19:48:57.719Z","etag":null,"topics":["angular","angular-forms","change-tracking","form-control-change-tracking","has-changes","has-form-changes"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IliaIdakiev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-15T14:07:37.000Z","updated_at":"2025-02-02T20:31:08.000Z","dependencies_parsed_at":"2023-02-18T04:46:06.637Z","dependency_job_id":null,"html_url":"https://github.com/IliaIdakiev/form-control-change-tracker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliaIdakiev%2Fform-control-change-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliaIdakiev%2Fform-control-change-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliaIdakiev%2Fform-control-change-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IliaIdakiev%2Fform-control-change-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IliaIdakiev","download_url":"https://codeload.github.com/IliaIdakiev/form-control-change-tracker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252095151,"owners_count":21693863,"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","angular-forms","change-tracking","form-control-change-tracking","has-changes","has-form-changes"],"created_at":"2024-11-12T18:27:15.210Z","updated_at":"2025-05-02T19:30:38.364Z","avatar_url":"https://github.com/IliaIdakiev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Angular Form Control Change Tracker\n\nVery often when developers need to know if there were any changes inside the a form in order to present a unsaved changes confirmation dialog when navigating away or in order to disable the save button when there is nothing new to save. The `FormControlChangeTrackerModule` provides two things: \n\n* The `ChangeTrackerDirective (hgChangeTracker)` that can be set on the individual form controls in order to track if any changes are made \n\n* And the `@hasChanges()` decorator that is applied over the `ChangeTrackerDirective` directives in order to provide you a boolean value indicating if there are any changes or not.\n\n## Usage:\n\n1. Import the module\n\nyour.module.ts\n```typescript\n@NgModule({\n  ...\n  imports: [\n    ...\n    FormControlChangeTrackerModule\n  ]\n})\nexport class AppModule { }\n```\n2. Add the directives and bind the initial value for each one.(the current example is using reactive forms but the module can be used with template driven forms as well. [Check out the demo app](https://stackblitz.com/github/IliaIdakiev/form-control-change-tracker))\n\nyour.component.html\n```html\n\u003cform [formGroup]=\"form\" (ngSubmit)=\"submit()\"\u003e\n  \u003cdiv class=\"form-group\"\u003e\n    \u003clabel\u003eFirst Name\u003c/label\u003e\n    \u003cinput type=\"text\" name=\"firstName\" formControlName=\"firstName\" hgChangeTracker\n      [initialValue]=\"firstNameDefaultValue\" /\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"form-group\"\u003e\n    \u003clabel\u003eLast Name\u003c/label\u003e\n    \u003cinput type=\"text\" name=\"lastName\" formControlName=\"lastName\" hgChangeTracker\n      [initialValue]=\"lastNameDefaultValue\" /\u003e\n  \u003c/div\u003e\n  \u003cbutton [disabled]=\"!hasFormChanges\"\u003eSubmit\u003c/button\u003e\n\u003c/form\u003e\n```\n\n3. Get the `hasFormChanges` value\n\nyour.component.ts\n```typescript\n@Component({\n  ...\n})\nexport class TemplateFromComponent {\n\n  @ViewChildren(ChangeTrackerDirective) @hasChanges() hasFormChanges: boolean;\n\n  ...\n\n}\n```\n\n**[Check out the demo app](https://stackblitz.com/github/IliaIdakiev/form-control-change-tracker)**\n\n4. More configurations\n\n### Decorator configuration\n\nyour.component.ts\n```typescript\n@Component({\n  ...\n})\nexport class TemplateFromComponent {\n\n  // ChangesWithValues\u003cT\u003e { hasChanges: boolean; values: { [P in keyof T]: { current: T[P]; initial: T[P]; }; }; } (very useful for debugging)\n  @ViewChildren(ChangeTrackerDirective) @hasChanges({ includeChangedValues: true }) formChangesData: ChangesWithValues\u003cT\u003e;\n  ...\n}\n```\n\n### Inputs\n\nchange-tracker.directive\n```typescript \n@Directive({\n  selector: '[ngModel][hgChangeTracker],[formControl][hgChangeTracker],[formControlName][hgChangeTracker]',\n  exportAs: 'hgChangeTracker'\n})\nexport class ChangeTrackerDirective {\n\n  @Input() multiInitialValue = false; // used for multiple initial values\n  @Input() autoInitialValueSync = true; // it can be used to disable the auto syncing of initialValue input\n\n  // whenever the auto sync is disabled this method needs to be manually called in order for the new initial value to be set\n  // keep in mind that the newValue is optional and if omitted the last change of the initialValue binding will be the new initial value\n  resetInitialValue(newValue?: T) { ... }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filiaidakiev%2Fform-control-change-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filiaidakiev%2Fform-control-change-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filiaidakiev%2Fform-control-change-tracker/lists"}