Skip to content

Commit f213484

Browse files
committed
Better handling of login form status
1 parent 2fe8b23 commit f213484

2 files changed

Lines changed: 66 additions & 60 deletions

File tree

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
<div class="col-md-6 offset-md-3 mt-5">
2-
<div class="card">
3-
<h4 class="card-header">Login</h4>
4-
<div class="card-body">
5-
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
6-
<div class="form-group">
7-
<label for="username">Username</label>
8-
<input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f['username'].errors }" />
9-
<div *ngIf="submitted && f['username'].errors" class="invalid-feedback">
10-
<div *ngIf="f['username'].errors['required']">Username is required</div>
11-
</div>
12-
</div>
13-
<div class="form-group">
14-
<label for="password">Password</label>
15-
<input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f['password'].errors }" />
16-
<div *ngIf="submitted && f['password'].errors" class="invalid-feedback">
17-
<div *ngIf="f['password'].errors['required']">Password is required</div>
18-
</div>
19-
</div>
20-
<button [disabled]="loading" class="btn btn-primary">
21-
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
22-
Login
23-
</button>
24-
<div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>
25-
</form>
26-
</div>
27-
</div>
2+
<div class="card">
3+
<h4 class="card-header">Login</h4>
4+
<div class="card-body">
5+
<form [formGroup]="form" (ngSubmit)="onSubmit()">
6+
<div class="form-group">
7+
<label for="username">Username</label>
8+
<input type="text" formControlName="username" class="form-control"
9+
[ngClass]="{ 'is-invalid': isFormInvalid() && form.get('username')?.errors }" />
10+
<div *ngIf="isFormInvalid() && form.get('username')?.hasError('required')" class="invalid-feedback">
11+
Username is required
12+
</div>
13+
</div>
14+
<div class="form-group">
15+
<label for="password">Password</label>
16+
<input type="password" formControlName="password" class="form-control"
17+
[ngClass]="{ 'is-invalid': isFormInvalid() && form.get('password')?.errors }" />
18+
<div *ngIf="isFormInvalid() && form.get('password')?.hasError('required')" class="invalid-feedback">
19+
Password is required
20+
</div>
21+
</div>
22+
<button [disabled]="!canLogin()" class="btn btn-primary">
23+
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
24+
Login
25+
</button>
26+
<div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>
27+
</form>
28+
</div>
29+
</div>
2830
</div>

src/app/login/login-form/login-form.component.ts

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,59 +10,63 @@ import { AuthenticationService } from '@app/authentication/service/authenticatio
1010
})
1111
export class LoginFormComponent implements OnInit {
1212

13-
loginForm: FormGroup;
14-
loading = false;
15-
submitted = false;
16-
returnUrl: string = '';
17-
error = '';
13+
public form = this.formBuilder.group({
14+
username: ['', Validators.required],
15+
password: ['', Validators.required]
16+
});
17+
18+
public loading = false;
19+
20+
public submitted = false;
21+
22+
public error = '';
23+
24+
private returnUrl: string = '';
1825

1926
constructor(
2027
private formBuilder: FormBuilder,
2128
private route: ActivatedRoute,
2229
private router: Router,
2330
private authenticationService: AuthenticationService
24-
) {
31+
) { }
32+
33+
ngOnInit() {
2534
// redirect to home if already logged in
2635
if (this.authenticationService.getUser().logged) {
2736
this.router.navigate(['/']);
2837
}
29-
30-
this.loginForm = this.formBuilder.group({
31-
username: ['', Validators.required],
32-
password: ['', Validators.required]
33-
});
34-
}
35-
36-
ngOnInit() {
3738
// get return url from route parameters or default to '/'
3839
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
3940
}
4041

41-
// convenience getter for easy access to form fields
42-
get f() { return this.loginForm.controls; }
43-
44-
onSubmit() {
42+
public onSubmit() {
4543
this.submitted = true;
4644

4745
// stop here if form is invalid
48-
if (this.loginForm.invalid) {
49-
return;
46+
if (this.form.valid) {
47+
this.loading = true;
48+
this.authenticationService.login(this.form.value.username, this.form.value.password)
49+
.subscribe({
50+
next: user => {
51+
this.loading = false;
52+
if (user.logged) {
53+
this.router.navigate([this.returnUrl]);
54+
}
55+
},
56+
error: error => {
57+
this.error = error;
58+
this.loading = false;
59+
}
60+
});
5061
}
62+
}
5163

52-
this.loading = true;
53-
this.authenticationService.login(this.f['username'].value, this.f['password'].value)
54-
.subscribe({
55-
next: user => {
56-
this.loading = false;
57-
if (user.logged) {
58-
this.router.navigate([this.returnUrl]);
59-
}
60-
},
61-
error: error => {
62-
this.error = error;
63-
this.loading = false;
64-
}
65-
});
64+
public isFormInvalid(): boolean {
65+
return this.form.invalid && (this.form.dirty || this.form.touched);
66+
}
67+
68+
public canLogin(): boolean {
69+
return this.form.valid;
6670
}
6771

6872
}

0 commit comments

Comments
 (0)