So I am trying to inject a shared data into a directive to be used by a validator to validate the email input by the user. My problem is I am getting 'undefined' for the value of my shared data from inside the directive. Here are the snippets:
registration.html
div class="form-group md-form" [class.has-error]="email.touched && email.dirty && email?.errors?.emailExist">
<i class="fa fa-envelope prefix grey-text"></i>
<input type="email" name="email" id="email" email="true" appCheckEmail [(ngModel)]="dealerRegistrationInput.email" #email="ngModel" class="form-control" placeholder="Email Address">
<div class="help-block alert alert-danger " *ngIf="email.errors && (email.dirty || email.touched) && email?.errors?.emailExist">
<div [hidden]="!email.errors.email">
A valid email is required.
</div>
<div [hidden]="email?.errors.emailExist">
This email address already exist
</div>
</div>
</div>
registration.ts
.......
constructor(
private router: Router,
private route: ActivatedRoute,
private http: HttpClient,
private sharedData: SharedDataService,
private connectService: ConnectService,
private modalService: BsModalService) { }
ngOnInit() {
this.connectService.getAllDealers().subscribe((dealers: Dealer[]) => {
this.sharedData.dealers = dealers;
console.log('Dealers.....' + JSON.stringify(this.sharedData.dealers));
});
}
............
.........
.............
check-mail directive
import { Input, Directive, forwardRef } from '@angular/core';
import { Validator, FormControl, AbstractControl, NG_VALIDATORS, ValidationErrors } from '@angular/forms';
import { SharedDataService } from './shared-data.service';
/* ......Functions.........................*/
function appCheckEmail(dealersEmails: string[]) {
console.log('Dealers..: ' + JSON.stringify(dealersEmails)); //THIS IS UNDEFINED
return (control: AbstractControl) => {
console.log('Dealers email addresses2: ' + JSON.stringify(dealersEmails));
console.log('Control value: ' + control.value)
...
...
if (dealersEmails.indexOf(control.value) >= 0) {
return null;
} else {
return{ emailnotExist: true };
}
};
}
/* -------------------------End of Functions.............*/
@Directive({
selector: '[appCheckEmail][ngModel], [appCheckEmail][ngModel]',
providers: [{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => CheckEmailDirective),
multi: true
}]
})
export class CheckEmailDirective implements Validator {
validator: Function;
constructor(private sharedData: SharedDataService) {
this.validator = appCheckEmail(sharedData.dealers); /* sharedData.dealers is undefined */
}
validate(control: AbstractControl): ValidationErrors | null {
return this.validator(control);
}
}
somehow the shared data in the directive despite the injection is not pointing to the correct reference or the value is cleared. I also observed something very curious ...the checkMail directive is been executed once the html is rendered...before any data entered and apparently on every keystroke of the targeted input field....could this behaviour be causing the problem? I would appreciate any help I can get.
--EDIT--
Having changed the appCheckEmail parameter to appCheckEmail(sharedData:SharedDataService)
and the indexOf search to:
if (sharedData.dealers.indexOf(control.value) >= 0){....}
The search still fails to find a match. I have confirmed with console.log that the sharedData.dealers array is in fact an array of strings and the control.value is a string with the values I am expecting. I have also tried simple for loop with:
if(sharedData.dealers[i] === control.value) I even tried: if(sharedData.dealers[i] === '[email protected]')
and both fails. I know I am a missing something fundamental here but I can't seem to find it. Could it be that sharedData.dealers[i] is still pointing to the wrong place even though I passed the reference in the constructor?
Instead of passing the dealers
to the validate function, you should pass the reference to your service to the function. The problem with your solution is the fact that the dealers
doesn't exist in the constructor
. You are fetching the dealers
in your Component
asynchronously, so they can't exist during build time in your Directive
constructor
import { Input, Directive, forwardRef } from '@angular/core';
import { Validator, FormControl, AbstractControl, NG_VALIDATORS, ValidationErrors } from '@angular/forms';
import { SharedDataService } from './shared-data.service';
/* ......Functions.........................*/
function appCheckEmail(sharedData: SharedDataService) {
return (control: AbstractControl) => {
console.log('Dealers email addresses2: ' + JSON.stringify(sharedData.dealersEmails));
console.log('Control value: ' + control.value)
...
...
if (sharedData.dealersEmails.indexOf(control.value) >= 0) {
return null;
} else {
return{ emailnotExist: true };
}
};
}
/* -------------------------End of Functions.............*/
@Directive({
selector: '[appCheckEmail][ngModel], [appCheckEmail][ngModel]',
providers: [{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => CheckEmailDirective),
multi: true
}]
})
export class CheckEmailDirective implements Validator {
validator: Function;
constructor(private sharedData: SharedDataService) {
this.validator = appCheckEmail(sharedData); /* sharedData.dealers is undefined */
}
validate(control: AbstractControl): ValidationErrors | null {
return this.validator(control);
}
}