Added some form elements and validation

This commit is contained in:
Erik Tiekstra
2021-04-15 11:32:19 +02:00
parent acfe221bab
commit 9fe6e0f91f
10 changed files with 216 additions and 2 deletions

View File

@@ -0,0 +1,4 @@
export interface ValidationError {
type: string;
message: string;
}

View File

@@ -6,5 +6,68 @@
rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum rutrum velit. Sed vitae ullamcorper sem. Aliquam malesuada nunc sed purus mollis scelerisque. Curabitur bibendum
leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est. leo quis ante porttitor tincidunt. Nam tincidunt imperdiet tortor eu suscipit. Maecenas ut dui est.
</p> </p>
<form [formGroup]="formGroup">
<div class="create-account__block">
<h2>Personuppgifter</h2>
<div class="create-account__combined-inputs">
<digi-ng-form-input
class="create-account__input"
formControlName="firstName"
afLabel="Förnamn"
afInvalidMessage="Förnamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="firstNameControl.invalid && firstNameControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="lastName"
afLabel="Efternamn"
afInvalidMessage="Efternamn är obligatoriskt"
[afDisableValidStyle]="true"
[afInvalid]="lastNameControl.invalid && lastNameControl.dirty"
></digi-ng-form-input>
</div>
<digi-ng-form-input
class="create-account__input"
formControlName="ssn"
afLabel="Personnummer"
[afInvalidMessage]="ssnControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="ssnControl.invalid && ssnControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="email"
afLabel="Arbetsmejl"
afType="email"
[afInvalidMessage]="ssnControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="ssnControl.invalid && ssnControl.dirty"
></digi-ng-form-input>
<digi-ng-form-input
class="create-account__input"
formControlName="phone"
afLabel="Telefonnummer arbete"
afType="tel"
[afInvalidMessage]="ssnControl.errors?.message || ''"
[afDisableValidStyle]="true"
[afInvalid]="ssnControl.invalid && ssnControl.dirty"
></digi-ng-form-input>
</div>
<div class="create-account__block">
<h2>Bemanning av personal</h2>
<fieldset>
<legend>Är {{ firstNameControl.value || 'medarbetaren' }} i aktiv tjänst?</legend>
<digi-ng-form-radiobutton-group
[afRadiobuttons]="activeRadioButtons"
formControlName="active"
></digi-ng-form-radiobutton-group>
</fieldset>
</div>
</form>
</digi-typography> </digi-typography>
</section> </section>

View File

@@ -0,0 +1,15 @@
.create-account {
&__block {
max-width: var(--digi--typography--text--max-width);
}
&__combined-inputs {
display: flex;
gap: var(--digi--layout--gutter);
}
&__input {
width: 100%;
margin-bottom: var(--digi--layout--gutter);
}
}

View File

@@ -1,4 +1,8 @@
import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group';
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
import { RequiredValidator } from '@dafa-validators/required.validator';
import { SocialSecurityNumberValidator } from '@dafa-validators/social-security-number.validator';
@Component({ @Component({
selector: 'dafa-create-account', selector: 'dafa-create-account',
@@ -6,4 +10,42 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
styleUrls: ['./create-account.component.scss'], styleUrls: ['./create-account.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class CreateAccountComponent {} export class CreateAccountComponent {
formGroup: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.formGroup = this.formBuilder.group({
firstName: this.formBuilder.control('', [RequiredValidator('Förnamn')]),
lastName: this.formBuilder.control('', [RequiredValidator('Efternamn')]),
ssn: this.formBuilder.control('', [RequiredValidator('Personnummer'), SocialSecurityNumberValidator()]),
email: this.formBuilder.control('', [RequiredValidator('Arbetsmejl')]),
phone: this.formBuilder.control('', [RequiredValidator('Telefonnummer arbete')]),
active: this.formBuilder.control(true),
});
this.formGroup.valueChanges.subscribe(values => console.table(values));
}
get activeRadioButtons(): RadiobuttonModel[] {
return [
{
label: 'Ja',
value: true,
},
{
label: 'Nej',
value: false,
},
];
}
get firstNameControl(): AbstractControl {
return this.formGroup.get('firstName');
}
get lastNameControl(): AbstractControl {
return this.formGroup.get('lastName');
}
get ssnControl(): AbstractControl {
return this.formGroup.get('ssn');
}
}

View File

@@ -1,11 +1,20 @@
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { CreateAccountComponent } from './create-account.component'; import { CreateAccountComponent } from './create-account.component';
@NgModule({ @NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [CreateAccountComponent], declarations: [CreateAccountComponent],
imports: [CommonModule, RouterModule.forChild([{ path: '', component: CreateAccountComponent }])], imports: [
CommonModule,
RouterModule.forChild([{ path: '', component: CreateAccountComponent }]),
ReactiveFormsModule,
DigiNgFormInputModule,
DigiNgFormRadiobuttonGroupModule,
],
}) })
export class CreateAccountModule {} export class CreateAccountModule {}

View File

@@ -0,0 +1,12 @@
import { AbstractControl, ValidatorFn } from '@angular/forms';
import { ValidationError } from '@dafa-models/validation-error.model';
export function RequiredValidator(label = 'Fältet'): ValidatorFn {
return (control: AbstractControl): ValidationError => {
if (control && !control.value) {
return { type: 'required', message: `${label} är obligatoriskt` };
}
return null;
};
}

View File

@@ -0,0 +1,68 @@
import { AbstractControl, ValidatorFn } from '@angular/forms';
import { ValidationError } from '@dafa-models/validation-error.model';
export function SocialSecurityNumberValidator(): ValidatorFn {
return (control: AbstractControl): ValidationError => {
if (!control || !control.value) {
return null;
}
const ssn = control.value;
if (/[^0-9-]/g.test(ssn)) {
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
}
let strippedSsn = control.value.replace(/[^0-9]/g, '');
// Year format 1991 -> 91
if (strippedSsn.length === 12) {
strippedSsn = strippedSsn.substr(2);
}
// Check length
if (strippedSsn.length !== 10) {
return { type: 'ssnNotComplete', message: 'Personnummret är inte fullständigt' };
}
// Check month
if (strippedSsn.substr(2, 2) > 12 || strippedSsn.substr(2, 2) === '00') {
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
}
// Check date (valid date + 60 is also apporved because of co-ordination number)
if (
(strippedSsn.substr(4, 2) > 31 || strippedSsn.substr(4, 2) === '00') &&
(strippedSsn.substr(4, 2) > 91 || strippedSsn.substr(4, 2) <= 60)
) {
return { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
}
return isControlDigitLegit(strippedSsn) ? null : { type: 'ssnInvalid', message: 'Inkorrekt personnummer' };
};
}
function isControlDigitLegit(ssn: string): boolean {
// Run the mod 10 algorithm to produce check digit
const enteredControlDigit = +ssn.substr(-1);
let inc = 0;
let multiplicator = 2;
let product: number;
for (const char of ssn.slice(0, -1)) {
product = +char * multiplicator;
if (product > 9) {
inc += product - 9;
} else {
inc += product;
}
multiplicator = multiplicator === 1 ? 2 : 1;
}
let calculatedControlDigit = 10 - (inc - Math.floor(inc / 10) * 10);
if (calculatedControlDigit === 10) {
calculatedControlDigit = 0;
}
return calculatedControlDigit === enteredControlDigit;
}

View File

@@ -23,6 +23,7 @@
"@dafa-enums/*": ["apps/dafa-web/src/app/data/enums/*"], "@dafa-enums/*": ["apps/dafa-web/src/app/data/enums/*"],
"@dafa-services/*": ["apps/dafa-web/src/app/services/*"], "@dafa-services/*": ["apps/dafa-web/src/app/services/*"],
"@dafa-utils/*": ["apps/dafa-web/src/app/utils/*"], "@dafa-utils/*": ["apps/dafa-web/src/app/utils/*"],
"@dafa-validators/*": ["apps/dafa-web/src/app/utils/validators/*"],
"@dafa-environment": ["apps/dafa-web/src/environments/environment"] "@dafa-environment": ["apps/dafa-web/src/environments/environment"]
} }
}, },