Skip to content

Commit f33c784

Browse files
committed
Fix password match validation
It must belong to FormGroup, not FormControl.
1 parent 37df342 commit f33c784

8 files changed

+35
-27
lines changed

src/app/core/forms/validator.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {FormControl} from "@angular/forms";
1+
import {FormControl, FormGroup} from "@angular/forms";
22
import {Validators} from "./validators";
33

44
describe('Validator', () => {
@@ -7,8 +7,8 @@ describe('Validator', () => {
77
it('validates the match of two controls', () => {
88
const ctrl1 = new FormControl('test1');
99
const ctrl2 = new FormControl('test2');
10-
expect(Validators.match(ctrl1)(ctrl1)).toBeUndefined();
11-
expect(Validators.match(ctrl1)(ctrl2)).toEqual({matched: false});
10+
expect(Validators.match(ctrl1, ctrl1)(new FormGroup({}))).toEqual({});
11+
expect(Validators.match(ctrl1, ctrl2)(new FormGroup({}))).toEqual({unmatched: true});
1212
});
1313
}); // .match
1414

src/app/core/forms/validators.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import {FormControl, ValidatorFn} from "@angular/forms";
22

33
export class Validators {
44

5-
static match(c1:FormControl):ValidatorFn {
6-
return (c2) => {
7-
if (c1.value !== c2.value) return {matched: false};
5+
static match(c1: FormControl, c2: FormControl): ValidatorFn {
6+
return (): {[key: string]: any} => {
7+
if (c1.value !== c2.value) return {unmatched: true};
8+
return {};
89
};
10+
911
}
1012

1113
}

src/app/pages/+signup/signup.component.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ <h1>Sign up</h1>
4242
[class.has-danger]="!password.valid && password.touched">
4343
<label class="col-form-label" for="passwordInput">Password</label>
4444
<input
45-
type="password"
45+
type="text"
4646
class="form-control form-control-danger"
4747
id="passwordInput"
4848
placeholder="Password"
@@ -57,11 +57,11 @@ <h1>Sign up</h1>
5757
</div>
5858

5959
<div class="form-group"
60-
[class.has-danger]="!passwordConfirmation.valid && passwordConfirmation.touched">
60+
[class.has-danger]="(!passwordConfirmation.valid || myForm.hasError('unmatched')) && passwordConfirmation.touched">
6161
<label class="col-form-label" for="passwordConfirmationInput">Confirm
6262
Password</label>
6363
<input
64-
type="password"
64+
type="text"
6565
class="form-control form-control-danger"
6666
id="passwordConfirmationInput"
6767
placeholder="Confirm Password"
@@ -71,7 +71,7 @@ <h1>Sign up</h1>
7171
class="form-control-feedback">Password confirmation is required
7272
</div>
7373
<div
74-
*ngIf="passwordConfirmation.hasError('matched') && passwordConfirmation.touched"
74+
*ngIf="myForm.hasError('unmatched') && passwordConfirmation.touched"
7575
class="form-control-feedback">Doesn't match
7676
</div>
7777
</div>

src/app/pages/+signup/signup.component.spec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ describe('SignupComponent', () => {
9797
body: JSON.stringify({token: 'my jwt'}),
9898
})));
9999
});
100-
page.onSubmit({
101-
email: 'test@test.com',
102-
password: 'secret',
103-
name: 'akira',
104-
});
105-
expect(authService.login).toHaveBeenCalledWith('test@test.com', 'secret');
100+
page.name.setValue('akira', {});
101+
page.email.setValue('test@test.com', {});
102+
page.password.setValue('secret123', {});
103+
page.passwordConfirmation.setValue('secret123', {});
104+
cmpDebugElement.query(By.css('button')).nativeElement.click();
105+
expect(authService.login).toHaveBeenCalledWith('test@test.com', 'secret123');
106106
advance(fixture);
107107
expect(location.path()).toEqual('/home');
108108
}));

src/app/pages/+signup/signup.component.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {EMAIL_PATTERN, Validators as AppValidators} from "../../core/forms";
55
import {UserService} from "../../core/services/user.service";
66
import {AuthService} from "../../core/services/auth.service";
77
import {ToastService} from "../../core/toast/toast.service";
8+
import values from "lodash/values";
89

910
@Component({
1011
selector: 'mpt-signup',
@@ -29,6 +30,10 @@ export class SignupComponent implements OnInit {
2930
}
3031

3132
onSubmit(params) {
33+
values(this.myForm.controls).forEach(c => c.markAsTouched());
34+
35+
if (!this.myForm.valid) return;
36+
3237
this.userService.create(params)
3338
.mergeMap(() => {
3439
return this.authService.login(params.email, params.password);
@@ -54,14 +59,13 @@ export class SignupComponent implements OnInit {
5459
]));
5560
this.passwordConfirmation = new FormControl('', Validators.compose([
5661
Validators.required,
57-
AppValidators.match(this.password),
5862
]));
5963
this.myForm = new FormGroup({
6064
name: this.name,
6165
email: this.email,
6266
password: this.password,
6367
passwordConfirmation: this.passwordConfirmation,
64-
});
68+
}, AppValidators.match(this.password, this.passwordConfirmation));
6569
}
6670

6771
private handleError(error) {

src/app/pages/+user-edit/user-edit.component.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ <h1>Update your profile</h1>
5454
</div>
5555

5656
<div class="form-group"
57-
[class.has-danger]="!passwordConfirmation.valid && passwordConfirmation.touched">
57+
[class.has-danger]="(!passwordConfirmation.valid || myForm.hasError('unmatched')) && passwordConfirmation.touched">
5858
<label class="col-form-label" for="passwordConfirmationInput">Confirm
5959
Password</label>
6060
<input
@@ -64,7 +64,7 @@ <h1>Update your profile</h1>
6464
placeholder="Confirm Password"
6565
formControlName="passwordConfirmation"/>
6666
<div
67-
*ngIf="passwordConfirmation.hasError('matched') && passwordConfirmation.touched"
67+
*ngIf="myForm.hasError('unmatched') && passwordConfirmation.touched"
6868
class="form-control-feedback">Doesn't match
6969
</div>
7070
</div>

src/app/pages/+user-edit/user-edit.component.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {FormGroup, FormControl, Validators} from "@angular/forms";
33
import {ActivatedRoute} from "@angular/router";
44
import isEmpty from "lodash/isEmpty";
55
import omitBy from "lodash/omitBy";
6+
import values from "lodash/values";
67
import {User} from "../../core/domains";
78
import {UserService} from "../../core/services/user.service";
89
import {EMAIL_PATTERN, Validators as AppValidators} from "../../core/forms";
@@ -35,8 +36,8 @@ export class UserEditComponent implements OnInit {
3536
}
3637

3738
onSubmit(params) {
38-
this.passwordConfirmation.updateValueAndValidity({});
39-
this.passwordConfirmation.markAsTouched();
39+
values(this.myForm.controls).forEach(c => c.markAsTouched());
40+
4041
if (!this.myForm.valid) return;
4142

4243
this.userService.updateMe(omitBy(params, isEmpty))
@@ -57,15 +58,13 @@ export class UserEditComponent implements OnInit {
5758
this.password = new FormControl('', Validators.compose([
5859
Validators.minLength(8),
5960
]));
60-
this.passwordConfirmation = new FormControl('', Validators.compose([
61-
AppValidators.match(this.password),
62-
]));
61+
this.passwordConfirmation = new FormControl('');
6362
this.myForm = new FormGroup({
6463
name: this.name,
6564
email: this.email,
6665
password: this.password,
6766
passwordConfirmation: this.passwordConfirmation,
68-
});
67+
}, AppValidators.match(this.password, this.passwordConfirmation));
6968
}
7069

7170
private handleError(error) {

src/vendor.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import "rxjs/add/operator/map";
22
import "rxjs/add/operator/mergeMap";
33
import "rxjs/add/operator/finally";
44
import "rxjs/add/operator/do";
5-
import "bootstrap/dist/css/bootstrap.css";
5+
import "lodash/values";
6+
import "lodash/isEmpty";
7+
import "lodash/omitBy";
68
import "jwt-decode";
9+
import "bootstrap/dist/css/bootstrap.css";
710

811
if ('production' === ENV) {
912
} else {

0 commit comments

Comments
 (0)