feat(ui): Added textarea component to ui-libs. (TV-849)
Squashed commit of the following: commit 61ecaf467c63cdd10f4d66131b105d3b12d60e49 Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Nov 3 11:14:19 2021 +0100 Removed unused input commit 2254c1dd547cbf3639e5232fe6d8e657491a369c Author: Erik Tiekstra <erik.tiekstra@arbetsformedlingen.se> Date: Wed Nov 3 11:12:38 2021 +0100 Implemented textarea component inside ui-libs
This commit is contained in:
@@ -24,19 +24,16 @@
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<digi-ng-form-textarea
|
<ui-textarea
|
||||||
formControlName="emails"
|
formControlName="emails"
|
||||||
afSize="m"
|
uiLabel="E-postadresser"
|
||||||
afDescription="För att skicka inbjudningar till flera e-postadresser samtidigt kan e-postadresser
|
uiDescription="För att skicka inbjudningar till flera e-postadresser samtidigt kan e-postadresser
|
||||||
separeras med bl.a. kommatecken eller mellanslag. Se fler exempel innanför textfältet nedan.
|
separeras med bl.a. kommatecken eller mellanslag. Se fler exempel innanför textfältet nedan.
|
||||||
Antalet mellanslag spelar inte roll och en blandning av tecknen går också bra."
|
Antalet mellanslag spelar inte roll och en blandning av tecknen går också bra."
|
||||||
afPlaceholder="namn@foretag.se namn@foretag.se, namn@foretag.se; namn@foretag.se:namn@foretag.se,namn@foretag.se: namn@foretag.se"
|
[uiRequired]="true"
|
||||||
[afRequired]="true"
|
[uiInvalid]="emailsControl.invalid && emailsControl.dirty"
|
||||||
[afDisableValidStyle]="true"
|
[uiValidationMessage]="emailsControl.errors?.required || emailsControl.errors?.invalid || 'Ogiltig e-postadress'"
|
||||||
[afInvalidMessage]="emailsControl.errors?.required || emailsControl.errors?.invalid || 'Ogiltig e-postadress'"
|
></ui-textarea>
|
||||||
[afInvalid]="emailsControl.invalid && emailsControl.dirty"
|
|
||||||
afLabel="E-postadresser"
|
|
||||||
></digi-ng-form-textarea>
|
|
||||||
|
|
||||||
<digi-notification-alert
|
<digi-notification-alert
|
||||||
*ngIf="(lastInvites$ | async) && !emailsControl.dirty"
|
*ngIf="(lastInvites$ | async) && !emailsControl.dirty"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
|
|
||||||
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 { ReactiveFormsModule } from '@angular/forms';
|
||||||
@@ -6,6 +5,7 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
|
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
|
||||||
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
import { UiLoaderModule } from '@ui/loader/loader.module';
|
import { UiLoaderModule } from '@ui/loader/loader.module';
|
||||||
|
import { UiTextareaModule } from '@ui/textarea/textarea.module';
|
||||||
import { EmployeeInviteComponent } from './employee-invite.component';
|
import { EmployeeInviteComponent } from './employee-invite.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -17,7 +17,7 @@ import { EmployeeInviteComponent } from './employee-invite.component';
|
|||||||
LayoutModule,
|
LayoutModule,
|
||||||
BackLinkModule,
|
BackLinkModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
DigiNgFormTextareaModule,
|
UiTextareaModule,
|
||||||
UiLoaderModule,
|
UiLoaderModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,16 +58,15 @@
|
|||||||
class="avvikelse-report-form__form-item"
|
class="avvikelse-report-form__form-item"
|
||||||
*ngFor="let question of questionsFormArray.controls; let i=index"
|
*ngFor="let question of questionsFormArray.controls; let i=index"
|
||||||
>
|
>
|
||||||
<digi-ng-form-textarea
|
<ui-textarea
|
||||||
[formControlName]="i"
|
[formControlName]="i"
|
||||||
[afLabel]="questions[i]?.name"
|
[uiLabel]="questions[i]?.name"
|
||||||
[afDisableValidStyle]="true"
|
[uiRequired]="questionIsRequired(questions[i])"
|
||||||
[afRequired]="questionIsRequired(questions[i])"
|
[uiValidationMessage]="question.errors?.required || question.errors?.invalid"
|
||||||
[afInvalidMessage]="question.errors?.required || question.errors?.invalid"
|
[uiAnnounceIfOptional]="true"
|
||||||
[afAnnounceIfOptional]="true"
|
[uiMaxLength]="2000"
|
||||||
[afMaxLength]="2000"
|
[uiInvalid]="formControlIsInvalid(question)"
|
||||||
[afInvalid]="formControlIsInvalid(question)"
|
></ui-textarea>
|
||||||
></digi-ng-form-textarea>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
|||||||
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
||||||
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
|
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
|
||||||
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
||||||
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
|
|
||||||
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
|
import { DigiNgProgressProgressbarModule } from '@af/digi-ng/_progress/progressbar';
|
||||||
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';
|
||||||
@@ -14,6 +13,7 @@ import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/conf
|
|||||||
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
import { UiLoaderModule } from '@ui/loader/loader.module';
|
import { UiLoaderModule } from '@ui/loader/loader.module';
|
||||||
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
||||||
|
import { UiTextareaModule } from '@ui/textarea/textarea.module';
|
||||||
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
||||||
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
||||||
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
|
import { AvvikelseReportFormComponent } from './avvikelse-report-form.component';
|
||||||
@@ -29,7 +29,6 @@ import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
DigiNgFormRadiobuttonGroupModule,
|
DigiNgFormRadiobuttonGroupModule,
|
||||||
DigiNgFormDatepickerModule,
|
DigiNgFormDatepickerModule,
|
||||||
DigiNgFormTextareaModule,
|
|
||||||
DigiNgProgressProgressbarModule,
|
DigiNgProgressProgressbarModule,
|
||||||
ReportLayoutModule,
|
ReportLayoutModule,
|
||||||
ConfirmDialogModule,
|
ConfirmDialogModule,
|
||||||
@@ -40,6 +39,7 @@ import { AvvikelseReportFormService } from './avvikelse-report-form.service';
|
|||||||
ReportDescriptionListModule,
|
ReportDescriptionListModule,
|
||||||
DigiNgFormInputModule,
|
DigiNgFormInputModule,
|
||||||
DigiNgDialogModule,
|
DigiNgDialogModule,
|
||||||
|
UiTextareaModule,
|
||||||
],
|
],
|
||||||
providers: [AvvikelseReportFormService],
|
providers: [AvvikelseReportFormService],
|
||||||
exports: [AvvikelseReportFormComponent],
|
exports: [AvvikelseReportFormComponent],
|
||||||
|
|||||||
@@ -87,24 +87,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="franvaro-report-form__form-item" *ngIf="showKnownReasonTextArea">
|
<div class="franvaro-report-form__form-item" *ngIf="showKnownReasonTextArea">
|
||||||
<digi-ng-form-textarea
|
<ui-textarea
|
||||||
[afDisableValidStyle]="true"
|
|
||||||
[afInvalid]="formControlIsInvalid(['knownReasonComment'])"
|
|
||||||
[afMaxLength]="2000"
|
|
||||||
[afAnnounceIfOptional]="true"
|
|
||||||
[afRequired]="true"
|
|
||||||
afLabel="Beskriv frånvaro"
|
|
||||||
afSize="s"
|
|
||||||
[formControl]="knownReasonCommentFormControl"
|
[formControl]="knownReasonCommentFormControl"
|
||||||
></digi-ng-form-textarea>
|
uiLabel="Beskriv frånvaro"
|
||||||
<div aria-atomic="true" role="alert">
|
[uiInvalid]="formControlIsInvalid(['knownReasonComment'])"
|
||||||
<digi-ng-form-validation-message
|
[uiValidationMessage]="formErrors?.knownReasonComment"
|
||||||
*ngIf="formControlIsInvalid(['knownReasonComment'])"
|
[uiMaxLength]="2000"
|
||||||
class="franvaro-report-form__validation-message"
|
[uiRequired]="true"
|
||||||
[afPositive]="false"
|
[uiAnnounceIfOptional]="true"
|
||||||
[afValidationText]="formErrors.knownReasonComment"
|
></ui-textarea>
|
||||||
></digi-ng-form-validation-message>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { DigiNgFormDatepickerModule } from '@af/digi-ng/_form/form-datepicker';
|
|||||||
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
import { DigiNgFormInputModule } from '@af/digi-ng/_form/form-input';
|
||||||
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
|
import { DigiNgFormRadiobuttonGroupModule } from '@af/digi-ng/_form/form-radiobutton-group';
|
||||||
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
||||||
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
|
|
||||||
import { DigiNgFormValidationMessageModule } from '@af/digi-ng/_form/form-validation-message';
|
import { DigiNgFormValidationMessageModule } from '@af/digi-ng/_form/form-validation-message';
|
||||||
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';
|
||||||
@@ -13,6 +12,7 @@ import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.modu
|
|||||||
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
import { UiLoaderModule } from '@ui/loader/loader.module';
|
import { UiLoaderModule } from '@ui/loader/loader.module';
|
||||||
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
||||||
|
import { UiTextareaModule } from '@ui/textarea/textarea.module';
|
||||||
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
||||||
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
||||||
import { FranvaroReportFormComponent } from './franvaro-report-form.component';
|
import { FranvaroReportFormComponent } from './franvaro-report-form.component';
|
||||||
@@ -34,10 +34,10 @@ import { FranvaroReportFormService } from './franvaro-report-form.service';
|
|||||||
DigiNgFormDatepickerModule,
|
DigiNgFormDatepickerModule,
|
||||||
DigiNgFormRadiobuttonGroupModule,
|
DigiNgFormRadiobuttonGroupModule,
|
||||||
UiSkeletonModule,
|
UiSkeletonModule,
|
||||||
DigiNgFormTextareaModule,
|
|
||||||
DigiNgFormInputModule,
|
DigiNgFormInputModule,
|
||||||
DigiNgFormValidationMessageModule,
|
DigiNgFormValidationMessageModule,
|
||||||
DigiNgDialogModule,
|
DigiNgDialogModule,
|
||||||
|
UiTextareaModule,
|
||||||
],
|
],
|
||||||
providers: [FranvaroReportFormService],
|
providers: [FranvaroReportFormService],
|
||||||
exports: [FranvaroReportFormComponent],
|
exports: [FranvaroReportFormComponent],
|
||||||
|
|||||||
@@ -61,17 +61,16 @@
|
|||||||
></digi-ng-form-select>
|
></digi-ng-form-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="informativ-rapport-form__form-item">
|
<div class="informativ-rapport-form__form-item">
|
||||||
<digi-ng-form-textarea
|
<ui-textarea
|
||||||
[formControl]="commentFormControl"
|
[formControl]="commentFormControl"
|
||||||
afLabel="Kompletterande information"
|
uiLabel="Kompletterande information"
|
||||||
afDescription="Undvik att skriva in information som känsliga personuppgifter, skyddad identitet eller deltagarens mående. Skriv i sådant fall in det telefonnummer du vill bli kontaktad på, vi bedömer om återkoppling är relevant."
|
uiDescription="Undvik att skriva in information som känsliga personuppgifter, skyddad identitet eller deltagarens mående. Skriv i sådant fall in det telefonnummer du vill bli kontaktad på, vi bedömer om återkoppling är relevant."
|
||||||
[afDisableValidStyle]="true"
|
[uiRequired]="true"
|
||||||
[afRequired]="true"
|
[uiInvalid]="formControlIsInvalid('comment')"
|
||||||
[afInvalidMessage]="commentFormControl.errors?.required"
|
[uiValidationMessage]="commentFormControl.errors?.required"
|
||||||
[afAnnounceIfOptional]="true"
|
[uiAnnounceIfOptional]="true"
|
||||||
[afMaxLength]="2000"
|
[uiMaxLength]="2000"
|
||||||
[afInvalid]="formControlIsInvalid('comment')"
|
></ui-textarea>
|
||||||
></digi-ng-form-textarea>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="informativ-rapport-form__footer">
|
<footer class="informativ-rapport-form__footer">
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
import { DigiNgDialogModule } from '@af/digi-ng/_dialog/dialog';
|
||||||
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
import { DigiNgFormSelectModule } from '@af/digi-ng/_form/form-select';
|
||||||
import { DigiNgFormTextareaModule } from '@af/digi-ng/_form/form-textarea';
|
|
||||||
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
|
||||||
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 { ReactiveFormsModule } from '@angular/forms';
|
||||||
@@ -9,6 +7,8 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
|
import { BackLinkModule } from '@msfa-shared/components/back-link/back-link.module';
|
||||||
import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/confirm-dialog.module';
|
import { ConfirmDialogModule } from '@msfa-shared/components/confirm-dialog/confirm-dialog.module';
|
||||||
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
import { LayoutModule } from '@msfa-shared/components/layout/layout.module';
|
||||||
|
import { UiSkeletonModule } from '@ui/skeleton/skeleton.module';
|
||||||
|
import { UiTextareaModule } from '@ui/textarea/textarea.module';
|
||||||
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
import { ReportDescriptionListModule } from '../../../components/report-description-list/report-description-list.module';
|
||||||
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
import { ReportLayoutModule } from '../../../components/report-layout/report-layout.module';
|
||||||
import { InformativRapportFormComponent } from './informativ-rapport-form.component';
|
import { InformativRapportFormComponent } from './informativ-rapport-form.component';
|
||||||
@@ -29,7 +29,7 @@ import { InformativRapportFormService } from './informativ-rapport-form.service'
|
|||||||
UiSkeletonModule,
|
UiSkeletonModule,
|
||||||
DigiNgDialogModule,
|
DigiNgDialogModule,
|
||||||
DigiNgFormSelectModule,
|
DigiNgFormSelectModule,
|
||||||
DigiNgFormTextareaModule,
|
UiTextareaModule,
|
||||||
],
|
],
|
||||||
providers: [InformativRapportFormService],
|
providers: [InformativRapportFormService],
|
||||||
exports: [InformativRapportFormComponent],
|
exports: [InformativRapportFormComponent],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* tslint:disable:no-unused-variable */
|
/* tslint:disable:no-unused-variable */
|
||||||
import { FormCheckboxComponent } from './form-checkbox.component';
|
import { CheckboxComponent } from './checkbox.component';
|
||||||
|
|
||||||
export class MockInjector {
|
export class MockInjector {
|
||||||
get = jest.fn();
|
get = jest.fn();
|
||||||
@@ -14,10 +14,10 @@ export class MockChangeDetectorRef {
|
|||||||
checkNoChanges = jest.fn();
|
checkNoChanges = jest.fn();
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('FormCheckboxComponent', () => {
|
describe('CheckboxComponent', () => {
|
||||||
let component: FormCheckboxComponent;
|
let component: CheckboxComponent;
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
component = new FormCheckboxComponent(new MockInjector(), new MockChangeDetectorRef());
|
component = new CheckboxComponent(new MockInjector(), new MockChangeDetectorRef());
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
OnChanges,
|
OnChanges,
|
||||||
Output,
|
Output,
|
||||||
SimpleChanges,
|
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ControlValueAccessor, NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { uuid } from '@utils/uuid.util';
|
import { uuid } from '@utils/uuid.util';
|
||||||
@@ -42,7 +41,7 @@ export class CheckboxComponent implements AfterViewInit, ControlValueAccessor, O
|
|||||||
@Input() uiId: string = uuid();
|
@Input() uiId: string = uuid();
|
||||||
@Input() uiName: string;
|
@Input() uiName: string;
|
||||||
@Input() uiAnnounceIfOptional: boolean = false;
|
@Input() uiAnnounceIfOptional: boolean = false;
|
||||||
@Output() uiOnChange: EventEmitter<any> = new EventEmitter();
|
@Output() uiOnChange: EventEmitter<boolean> = new EventEmitter();
|
||||||
|
|
||||||
name: string | number;
|
name: string | number;
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ export class CheckboxComponent implements AfterViewInit, ControlValueAccessor, O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(): void {
|
||||||
const ngControl: NgControl = this.injector.get(NgControl, null);
|
const ngControl: NgControl = this.injector.get(NgControl, null);
|
||||||
if (ngControl) {
|
if (ngControl) {
|
||||||
this.name = ngControl.name;
|
this.name = ngControl.name;
|
||||||
@@ -96,7 +95,7 @@ export class CheckboxComponent implements AfterViewInit, ControlValueAccessor, O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: any): void {
|
writeValue(value: boolean): void {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|||||||
6
libs/ui/src/textarea/textarea-variation.enum.ts
Normal file
6
libs/ui/src/textarea/textarea-variation.enum.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export enum UiTextAreaVariation {
|
||||||
|
AUTO = 'auto',
|
||||||
|
S = 's',
|
||||||
|
M = 'm',
|
||||||
|
L = 'l',
|
||||||
|
}
|
||||||
26
libs/ui/src/textarea/textarea.component.html
Normal file
26
libs/ui/src/textarea/textarea.component.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<div
|
||||||
|
class="ui-textarea"
|
||||||
|
[ngClass]="{'ui-textarea--invalid': uiInvalid && uiValidationMessage, 'ui-textarea--with-counter': uiMaxLength}"
|
||||||
|
>
|
||||||
|
<digi-form-textarea
|
||||||
|
class="ui-textarea__textarea"
|
||||||
|
[afId]="uiId"
|
||||||
|
[afName]="uiName"
|
||||||
|
[afLabel]="uiLabel"
|
||||||
|
[afLabelDescription]="uiDescription"
|
||||||
|
[afVariation]="uiVariation"
|
||||||
|
[afRequired]="uiRequired"
|
||||||
|
[afAnnounceIfOptional]="uiAnnounceIfOptional"
|
||||||
|
[afMaxlength]="uiMaxLength"
|
||||||
|
[afMinlength]="uiMinLength"
|
||||||
|
[afValue]="currentValue"
|
||||||
|
[afValidation]="uiInvalid ? 'error' : 'neutral'"
|
||||||
|
(afOnInput)="checkForChange($event.detail.target.value)"
|
||||||
|
></digi-form-textarea>
|
||||||
|
<span class="ui-textarea__counter" *ngIf="uiMaxLength">{{charactersLeft}} tecken kvar</span>
|
||||||
|
<div class="ui-textarea__validation" aria-atomic="true" role="alert">
|
||||||
|
<digi-form-validation-message *ngIf="uiInvalid && uiValidationMessage" af-variation="error"
|
||||||
|
>{{uiValidationMessage}}</digi-form-validation-message
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
25
libs/ui/src/textarea/textarea.component.scss
Normal file
25
libs/ui/src/textarea/textarea.component.scss
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.ui-textarea {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr max-content;
|
||||||
|
grid-template-areas:
|
||||||
|
'textarea textarea'
|
||||||
|
'validation counter';
|
||||||
|
|
||||||
|
&--invalid,
|
||||||
|
&--with-counter {
|
||||||
|
gap: var(--digi--layout--gutter--s);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__textarea {
|
||||||
|
grid-area: textarea;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__counter {
|
||||||
|
grid-area: counter;
|
||||||
|
color: var(--digi--typography--color--text--dimmed);
|
||||||
|
font-size: var(--digi--typography--font-size--s);
|
||||||
|
}
|
||||||
|
&__validation {
|
||||||
|
grid-area: validation;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
libs/ui/src/textarea/textarea.component.spec.ts
Normal file
23
libs/ui/src/textarea/textarea.component.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
import { TextareaComponent } from './textarea.component';
|
||||||
|
|
||||||
|
export class MockInjector {
|
||||||
|
get = jest.fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line: max-classes-per-file
|
||||||
|
export class MockChangeDetectorRef {
|
||||||
|
markForCheck = jest.fn();
|
||||||
|
detach = jest.fn();
|
||||||
|
detectChanges = jest.fn();
|
||||||
|
reattach = jest.fn();
|
||||||
|
checkNoChanges = jest.fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TextareaComponent', () => {
|
||||||
|
let component: TextareaComponent;
|
||||||
|
it('should create', () => {
|
||||||
|
component = new TextareaComponent(new MockInjector(), new MockChangeDetectorRef());
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
16
libs/ui/src/textarea/textarea.component.stories.ts
Normal file
16
libs/ui/src/textarea/textarea.component.stories.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { TextareaComponent } from './textarea.component';
|
||||||
|
import { UiTextareaModule } from './textarea.module';
|
||||||
|
|
||||||
|
export default { title: 'Textarea', component: TextareaComponent };
|
||||||
|
|
||||||
|
const componentModule = {
|
||||||
|
moduleMetadata: {
|
||||||
|
imports: [ReactiveFormsModule, UiTextareaModule],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const standard = () => ({
|
||||||
|
...componentModule,
|
||||||
|
template: '<ui-textarea></ui-textarea>',
|
||||||
|
});
|
||||||
101
libs/ui/src/textarea/textarea.component.ts
Normal file
101
libs/ui/src/textarea/textarea.component.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Injector,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
Output,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ControlValueAccessor, NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
import { uuid } from '@utils/uuid.util';
|
||||||
|
import { UiTextAreaVariation } from './textarea-variation.enum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A textarea input. Implemented with control value accessor
|
||||||
|
*
|
||||||
|
* ## Usage
|
||||||
|
* ``import {UiTextareaModule} from '@ui/textarea/textarea.module';``
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ui-textarea',
|
||||||
|
templateUrl: './textarea.component.html',
|
||||||
|
styleUrls: ['./textarea.component.scss'],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: NG_VALUE_ACCESSOR,
|
||||||
|
useExisting: TextareaComponent,
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class TextareaComponent implements AfterViewInit, ControlValueAccessor, OnChanges {
|
||||||
|
@Input() uiId: string = uuid();
|
||||||
|
@Input() uiName: string;
|
||||||
|
@Input() uiLabel: string = '';
|
||||||
|
@Input() uiDescription: string;
|
||||||
|
@Input() uiVariation: UiTextAreaVariation = UiTextAreaVariation.M;
|
||||||
|
@Input() uiRequired: boolean;
|
||||||
|
@Input() uiAnnounceIfOptional: boolean = false;
|
||||||
|
@Input() uiMaxLength: number;
|
||||||
|
@Input() uiMinLength: number;
|
||||||
|
@Input() uiInvalid: boolean;
|
||||||
|
@Input() uiValidationMessage: string;
|
||||||
|
@Output() uiOnChange: EventEmitter<string> = new EventEmitter();
|
||||||
|
|
||||||
|
name: string | number;
|
||||||
|
|
||||||
|
onTouched: () => {};
|
||||||
|
private onChange: (value: any) => {};
|
||||||
|
private _value: string = '';
|
||||||
|
|
||||||
|
constructor(private injector: Injector, private changeDetectorRef: ChangeDetectorRef) {}
|
||||||
|
|
||||||
|
get currentValue(): string {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get charactersLeft(): number {
|
||||||
|
return this.uiMaxLength - this.currentValue.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
const ngControl: NgControl = this.injector.get(NgControl, null);
|
||||||
|
if (ngControl) {
|
||||||
|
this.name = ngControl.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(): void {
|
||||||
|
const ngControl: NgControl = this.injector.get(NgControl, null);
|
||||||
|
if (ngControl) {
|
||||||
|
this.name = ngControl.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForChange(value: string): void {
|
||||||
|
if (this._value !== value) {
|
||||||
|
if (this.onChange) {
|
||||||
|
this.onChange(value);
|
||||||
|
}
|
||||||
|
this._value = value;
|
||||||
|
this.uiOnChange.emit(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(value: string): void {
|
||||||
|
this._value = value;
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: (value: string) => {}) {
|
||||||
|
this.onChange = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnTouched(fn: () => {}) {
|
||||||
|
this.onTouched = fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
libs/ui/src/textarea/textarea.module.ts
Normal file
11
libs/ui/src/textarea/textarea.module.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { TextareaComponent } from './textarea.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
|
imports: [CommonModule],
|
||||||
|
declarations: [TextareaComponent],
|
||||||
|
exports: [TextareaComponent],
|
||||||
|
})
|
||||||
|
export class UiTextareaModule {}
|
||||||
Reference in New Issue
Block a user