]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core'; |
2 | import { AbstractControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms'; | |
3 | ||
f67539c2 TL |
4 | import _ from 'lodash'; |
5 | ||
6 | import { Icons } from '~/app/shared/enum/icons.enum'; | |
11fdf7f2 TL |
7 | |
8 | /** | |
9 | * This component will render a submit button with the given label. | |
10 | * | |
11 | * The button will disabled itself and show a loading icon when the user clicks | |
12 | * it, usually initiating a request to the server, and it will stay in that | |
13 | * state until the request is finished. | |
14 | * | |
15 | * To indicate that the request failed, returning the button to the enable | |
16 | * state, you need to insert an error in the form with the 'cdSubmitButton' key. | |
17 | * p.e.: this.rbdForm.setErrors({'cdSubmitButton': true}); | |
18 | * | |
19 | * It will also check if the form is valid, when clicking the button, and will | |
20 | * focus on the first invalid input. | |
21 | * | |
22 | * @export | |
23 | * @class SubmitButtonComponent | |
24 | * @implements {OnInit} | |
25 | */ | |
26 | @Component({ | |
27 | selector: 'cd-submit-button', | |
28 | templateUrl: './submit-button.component.html', | |
29 | styleUrls: ['./submit-button.component.scss'] | |
30 | }) | |
31 | export class SubmitButtonComponent implements OnInit { | |
32 | @Input() | |
33 | form: FormGroup | NgForm; | |
9f95a23c | 34 | |
11fdf7f2 TL |
35 | @Input() |
36 | type = 'submit'; | |
9f95a23c | 37 | |
11fdf7f2 TL |
38 | @Input() |
39 | disabled = false; | |
40 | ||
9f95a23c TL |
41 | // A CSS class string to apply to the button's main element. |
42 | @Input() | |
43 | btnClass: string; | |
44 | ||
2a845540 TL |
45 | @Input() |
46 | ariaLabel: string; | |
47 | ||
9f95a23c TL |
48 | @Output() |
49 | submitAction = new EventEmitter(); | |
50 | ||
11fdf7f2 | 51 | loading = false; |
9f95a23c | 52 | icons = Icons; |
11fdf7f2 TL |
53 | |
54 | constructor(private elRef: ElementRef) {} | |
55 | ||
56 | ngOnInit() { | |
57 | this.form.statusChanges.subscribe(() => { | |
58 | if (_.has(this.form.errors, 'cdSubmitButton')) { | |
59 | this.loading = false; | |
60 | _.unset(this.form.errors, 'cdSubmitButton'); | |
61 | // Handle Reactive forms. | |
62 | if (this.form instanceof AbstractControl) { | |
63 | (<AbstractControl>this.form).updateValueAndValidity(); | |
64 | } | |
65 | } | |
66 | }); | |
67 | } | |
68 | ||
9f95a23c | 69 | submit($event: any) { |
11fdf7f2 TL |
70 | this.focusButton(); |
71 | ||
72 | // Special handling for Template driven forms. | |
73 | if (this.form instanceof FormGroupDirective) { | |
74 | (<FormGroupDirective>this.form).onSubmit($event); | |
75 | } | |
76 | ||
77 | if (this.form.invalid) { | |
78 | this.focusInvalid(); | |
79 | return; | |
80 | } | |
81 | ||
82 | this.loading = true; | |
83 | this.submitAction.emit(); | |
84 | } | |
85 | ||
86 | focusButton() { | |
87 | this.elRef.nativeElement.offsetParent.querySelector(`button[type="${this.type}"]`).focus(); | |
88 | } | |
89 | ||
90 | focusInvalid() { | |
91 | const target = this.elRef.nativeElement.offsetParent.querySelector( | |
92 | 'input.ng-invalid, select.ng-invalid' | |
93 | ); | |
94 | ||
95 | if (target) { | |
96 | target.focus(); | |
97 | } | |
98 | } | |
99 | } |