Reputation: 848
I'm working with a simple angular5 app in front end , using HTTPCLIENT , and spring-boot in back-end , i'm creating a simple component to add a new client,with field username .
i'm trying to use custum validator so i can check if the username is unique or already used , but i'm fascing many errors . This is Angular side
new-client.component.html
<div >
<div class="col-sm-10">
<div class="card">
<div class="card-header">
<strong>add a new client</strong>
</div>
<form [formGroup]="form" (ngSubmit)="SaveClient()">
<div class="card-body">
<div class="form-group">
<label for="vat">Email </label>
<input type="text" class="form-control" id="vat" formControlName="username" />
<div class="error" *ngIf="form.controls['username'].invalid && form.controls['username'].errors.required && (form.controls['username'].dirty || form.controls['username'].touched)">Please enter an email</div>
<div class="error" *ngIf="form.controls['username'].invalid && form.controls['username'].errors.email && (form.controls['username'].dirty || form.controls['username'].touched)">Please enter a valid email</div>
<div class="error" *ngIf="form.controls['username'].invalid && form.controls['username'].errors.emailTaken">This email has been taken, please use another one.</div>
</div>
<div formGroupName = "passwordG">
<div class="form-group">
<label for="vat">Password</label>
<input type="password" class="form-control" id="vat" formControlName="password" />
</div>
<div class="form-group">
<label for="vat">Confirmation Password</label>
<input type="password" class="form-control" id="vat" formControlName="Confirmationpassword" />
</div>
<div *ngIf="(form.controls['passwordG'].invalid && form.controls['passwordG'].touched)" class="col-sm-3 text-danger">
<ng-container *ngIf="form.controls['passwordG'].errors?.mismatch;
then first else second"> </ng-container>
<ng-template #first>
Password do not match </ng-template>
<ng-template #second>
Password needs to be more than 8 characters
</ng-template>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-sm btn-primary" ><i class="fa fa-dot-circle-o"></i>Enregistrer</button>
</div>
</form>
</div>
</div><!--/.col-->
</div>
new-client.component.ts
function passwordMatch(control: AbstractControl):{[key: string]: boolean}{
const password = control.get('password');
const Confirmationpassword = control.get('Confirmationpassword');
if( !password || !Confirmationpassword) {
return null; }
if(password.value === Confirmationpassword.value){
return null;
}
return {
mismatch:true
}
}
@Component({
selector: 'app-new-clients',
templateUrl: './new-clients.component.html',
styleUrls: ['./new-clients.component.scss']
})
export class NewClientsComponent implements OnInit {
client:Clients = new Clients();
form: FormGroup;
constructor(private clientService:ClientService,
private formBuilder: FormBuilder,
public router:Router,
public activatedRoute:ActivatedRoute) { }
ngOnInit() {
this.form = this.formBuilder.group({
username: ['', Validators.required , Validators.email , this.validateEmailNotTaken.bind(this)],
passwordG: this.formBuilder.group({
password: ['',[Validators.required,Validators.minLength(9)]],
Confirmationpassword : ['',[Validators.required,Validators.minLength(9)]]
}, {validator: passwordMatch})
});
}
SaveClient(){
this.client.setUsername(this.form.value.username);
this.client.setPassword(this.form.value.passwordG.password);
this.clientService.saveClient(this.client)
.subscribe((data:Clients)=>{
swal("operation réussi !", "great !", "success");
this.router.navigate([ '../list' ], { relativeTo: this.activatedRoute });
},err=>{
console.log(err);
})
}
validateEmailNotTaken(control: AbstractControl) {
return this.clientService.checkEmailNotTaken(control.value).map(res => {
return res ? null : { emailTaken: true };
}); //somthing is wrong HERE !
}
}
client.service.ts
@Injectable()
export class ClientService {
checkEmailNotTaken(email:string){
if(this.authService.getToken()==null) {
this.authService.loadToken();
}
return this.http.post(this.host+
"/checkEmailUnique/",{email},{headers:new HttpHeaders({'Authorization':this.authService.getToken()})});
}
}
In spring-boot :
@RequestMapping(value="/checkEmailUnique",method=RequestMethod.POST)
public EmailStatusCheckJson checkEmailUnique(@RequestBody final AppUser appUser){
final EmailStatusCheckJson returnValue = new EmailStatusCheckJson();
System.out.println("username **"+appUser.getUsername());
AppUser app = userRepo.findByUsername(appUser.getUsername());
if(app!=null){
System.out.println("exists");
returnValue.setEmailIsAvailable(false);
}
else{
System.out.println("doesnt exist ");
returnValue.setEmailIsAvailable(true);
}
return returnValue;
}
This is the error i'm getting
ERROR Error: Expected validator to return Promise or Observable.
at toObservable (forms.js:749)
at Array.map (<anonymous>)
at FormControl.eval [as asyncValidator] (forms.js:729)
at FormControl.AbstractControl._runAsyncValidator (forms.js:3447)
at FormControl.AbstractControl.updateValueAndValidity (forms.js:3390)
at FormControl.setValue (forms.js:3973)
Any idea ? I'm new to angular .
Upvotes: 0
Views: 460
Reputation: 691735
What is expacted for a control is
So it should be
['', [Validators.required, Validators.email], this.validateEmailNotTaken.bind(this)]
since the validateEmailNotTaken
is an async validator.
Upvotes: 1
Reputation: 32517
You are missing bracket here
username: ['', Validators.required , Validators.email , this.validateEmailNotTaken.bind(this)]
should be
username: ['', [Validators.required , Validators.email , this.validateEmailNotTaken.bind(this)]]
Upvotes: 1