Last active
June 28, 2021 12:44
-
-
Save pdashford/3e9338cafac51424c6607550eee4c484 to your computer and use it in GitHub Desktop.
Custom Angular FormGroup which maintains the initial form state. Provides a valuesChanged Observable which only provides real modified values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { EventEmitter } from '@angular/core' | |
import { | |
FormGroup, | |
AbstractControl, | |
ValidatorFn, | |
AbstractControlOptions, | |
AsyncValidatorFn | |
} from '@angular/forms' | |
/** | |
* | |
* | |
* @export | |
* @class FormGroupState | |
* @extends {FormGroup} | |
*/ | |
export class FormGroupState extends FormGroup { | |
public readonly valuesChanged!: EventEmitter<any> | |
private _state = [] | |
private _changed = {} | |
constructor( | |
controls: { | |
[key: string]: AbstractControl | |
}, | |
validatorOrOpts?: | |
| ValidatorFn | |
| ValidatorFn[] | |
| AbstractControlOptions | |
| null, | |
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null | |
) { | |
super(controls, validatorOrOpts, asyncValidator) | |
this.valuesChanged = new EventEmitter() | |
this.valueChanges.subscribe((changes) => { | |
if (this._state.length) { | |
this._changed = {} | |
Object.keys(changes) | |
.filter((key) => this._state.map((m) => m.name).includes(key)) | |
.forEach((controlName) => { | |
const controlValue = this.controls[controlName].value | |
if ( | |
controlValue !== | |
this._state.find((f) => f.name === controlName).value | |
) { | |
Object.assign(this._changed, { | |
[controlName]: controlValue | |
}) | |
} | |
}) | |
this.valuesChanged.emit(this._changed) | |
} | |
}) | |
} | |
setInitialState( | |
value: { [key: string]: any }, | |
options?: { | |
onlySelf?: boolean | |
emitEvent?: boolean | |
} | |
): void { | |
super.patchValue(value, options) | |
this._state = [] | |
Object.keys(this.controls).forEach((name) => { | |
this._state.push({ name, value: this.controls[name].value }) | |
}) | |
} | |
get changedValues() { | |
return this._changed | |
} | |
} | |
/*************************************************************************************************** | |
* Custom FormGroup which maintains an initial form state so that only 'real' changes are reported | |
* | |
* Example: | |
* | |
* formGroup = new FormGroupState({ | |
* name: new FormControl(''), | |
* id: new FormControl('') | |
* }) | |
* | |
* // Sets the iniitial form values and state | |
* this.formGroup.setInitialState({ name: 'welcome', id: 0}, { emitEvent: false }) | |
* | |
* // Only the real changes will be reported here.... | |
* this.formGroup.valuesChanged.subscribe(changes => console.log(changes)) | |
* | |
/***************************************************************************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment