Custom validator for uniqueness in Angular2
angular, typescript
Solution
simple: when assigning the validator you bind the this argument of your class to it, like so: `'code : ['', this.codeUnique.bind(this)]`
Problem
I have an Angular2 form field. I want to require that the entered value doesn't already exist. My component receives the array of existing values via an @Input parameter. I have a custom validator function in my component, codeUnique(), but when it's executed it has no access to instance members. "this" returns either FormControl or undefined. My validator function has been sucked into outer space, stripped of it's context and instance variables. How can I get my list of existing values into my validator? Could I put them in a global scope, horror? ``` import { Component, Input, Output, EventEmitter } from '@angular/core'; import { NG_VALIDATORS, FormControl, FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms'; import { ReferringAppModel } from './referringapp.model'; //import { CodeValidator } from './code-validator'; @Component({ selector: 'add-client-form', templateUrl: 'src/home/add-client-form.component.html' }) export class AddClientFormComponent { myForm: FormGroup; code: AbstractControl; name: AbstractControl; constructor(fb: FormBuilder) { this.myForm = fb.group({ 'code': ['', this.codeUnique], 'name': ['', Validators.required] }); this.code = this.myForm.controls['code']; this.name = this.myForm.controls['name']; } @Input() referringApps: ReferringAppModel[]; ngOnInit() { } onSubmit(form: any): void { console.log("submitted") }; codeUnique(c: FormControl) { try { // Blows up. return !this.referringApps.find(appInApps => appInApps.Code == c.value) ? null : { //return false ? null : { // WORKS validateEmail: { valid: false } }; } catch (ex) { console.log(ex); } } } TypeError: Cannot read property 'referringApps' of undefined at AddClientFormComponent.codeUnique (http://localhost/HubHacienda/dist/bundle.js:50071:26) at http://localhost/HubHacienda/dist/bundle.js:43538:54 at Array.map (native) at _executeValidators (http://localhost/HubHacienda/dist/bundle.js:43538:28) at FormControl.Validators.compose [as validator] (http://localhost/HubHacienda/dist/bundle.js:43518:38) at FormControl.AbstractControl._runValidator (http://localhost/HubHacienda/dist/bundle.js:45083:54) at FormControl.AbstractControl.updateValueAndValidity (http://localhost/HubHacienda/dist/bundle.js:45061:38) at FormControl.setValue (http://localhost/HubHacienda/dist/bundle.js:45327:19) at DefaultValueAccessor.onChange (http://localhost/HubHacienda/dist/bundle.js:44287:22) at DebugAppView._View_AddClientFormComponent0._handle_input_12_0 (AddClientFormComponent.ngfactory.js:493:47) at DebugAppView.eventHandler (http://localhost/HubHacienda/dist/bundle.js:35576:29) at COMPONENT_REGEX (http://localhost/HubHacienda/dist/bundle.js:38521:41) at http://localhost/HubHacienda/dist/bundle.js:38634:116 at ZoneDelegate.invoke (http://localhost/HubHacienda/dist/bundle.js:6875:29) at Object.onInvoke (http://localhost/HubHacienda/dist/bundle.js:32132:42) at ZoneDelegate.invoke (http://localhost/HubHacienda/dist/bundle.js:6874:35) at Zone.runGuarded (http://localhost/HubHacienda/dist/bundle.js:6782:48) at NgZoneImpl.runInnerGuarded (http://localhost/HubHacienda/dist/bundle.js:32161:83) at NgZone.runGuarded (http://localhost/HubHacienda/dist/bundle.js:32393:78) at HTMLInputElement.outsideHandler (http://localhost/HubHacienda/dist/bundle.js:38634:84) at ZoneDelegate.invokeTask (http://localhost/HubHacienda/dist/bundle.js:6908:38) at Zone.runTask (http://localhost/HubHacienda/dist/bundle.js:6808:48) at HTMLInputElement.ZoneTask.ZoneTask.cancelFn.invoke (http://localhost/HubHacienda/dist/bundle.js:6976:34) ```