Created
March 13, 2024 11:10
-
-
Save ko1ebayev/95db8d5bbb71c41bbaf00dcc7ffccf5d to your computer and use it in GitHub Desktop.
Empowered angular form control
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
type StatusChange = (property: string, previousValue: any, value: any) => void; | |
interface EmpoweredStatus { | |
property: string; | |
value: any; | |
previousValue: any; | |
} | |
class EmpoweredFormControl<T extends AbstractControl> { | |
private static readonly EMPOWER_KEY = '##empower##'; | |
private statusChangeHandlers: StatuChange[] = []; | |
private empoweredStatusSubject = new Subject<EmpoweredStatus>(); | |
static getEmpoweredControl<T extends AbstractControl>(abstractControl: T): EmpoweredFormControl<T> { | |
if (!abstractControl[EmpoweredFormControl.EMPOWER_KEY]) { | |
abstractControl[EmpoweredFormControl.EMPOWER_KEY] = new EmpoweredFormControl(abstractControl); | |
} | |
return abstractControl[EmpoweredFormControl.EMPOWER_KEY]; | |
} | |
static destroyEmpoweredControl<T extends AbstractControl>(abstractControl: T): void { | |
if (abstractControl[EmpoweredFormControl.EMPOWER_KEY]) { | |
delete abstractControl[EmpoweredFormControl.EMPOWER_KEY]; | |
} | |
} | |
private constructor(readonly abstractControl: T) { | |
this.empowerAbstractControl(this.abstractControl); | |
} | |
destroy() { | |
this.statusChangeHandlers = null; | |
EmpoweredFormControl.destroyEmpoweredControl(this.abstractControl); | |
} | |
registerStatusChange(fn: StatuChange): void { | |
this.statusChangeHandlers.push(fn); | |
} | |
get empoweredStatusChange(): Observable<EmpoweredStatus> { | |
return this.empoweredStatusSubject.asObservable(); | |
} | |
private change(property: string, previousValue: any, currentValue: any) { | |
this.statusChangeHandlers.forEach(handler => { | |
handler(property, previousValue, currentValue); | |
}); | |
} | |
private empowerAbstractControl(abstractControl: T) { | |
['touched', 'pristine'].forEach(property => { | |
for (let baseProperty of ['_' + property, property]) { | |
let propertyValue: any = abstractControl[baseProperty]; | |
if (propertyValue !== undefined) { | |
Object.defineProperty(abstractControl, baseProperty, { | |
get: () => propertyValue, | |
set: (value: any) => { | |
let previousValue = propertyValue; | |
propertyValue = value; | |
this.change(property, previousValue, propertyValue); | |
} | |
}); | |
break; | |
} | |
} | |
}); | |
this.registerStatusChange((property: string, previousValue: any, value: any) => { | |
this.empoweredStatusSubject.next({ | |
property, | |
value, | |
previousValue | |
}); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment