added dynamic input component

This commit is contained in:
Valentin Mihai 2023-01-25 22:01:28 +02:00
parent 1bef72a321
commit eb84e5f348
7 changed files with 129 additions and 6 deletions

View File

@ -1,9 +1,13 @@
@use 'common-mixins' as mixins;
form .iqser-input-group:not(first-of-type) {
form .iqser-input-group:not(first-of-type), iqser-dynamic-input:not(first-of-type) {
margin-top: 14px;
}
iqser-dynamic-input {
display: flex;
}
.iqser-input-group {
display: flex;
flex-direction: column;

View File

@ -26,6 +26,7 @@ export abstract class BaseDialogComponent implements OnDestroy {
protected readonly _toaster = inject(Toaster);
readonly #confirmationDialogService = inject(ConfirmationDialogService);
readonly #dialog = inject(MatDialog);
#hasErrors = false;
#backdropClickSubscription = this._dialogRef.backdropClick().subscribe(() => {
this.close();
});
@ -41,7 +42,7 @@ export abstract class BaseDialogComponent implements OnDestroy {
}
get disabled(): boolean {
return !this.valid || !this.changed;
return !this.valid || !this.changed || this.#hasErrors;
}
abstract save(options?: SaveOptions): void;
@ -82,6 +83,11 @@ export abstract class BaseDialogComponent implements OnDestroy {
}
}
@HostListener('window:keyup', ['$event'])
onKeyUp(): void {
this.#hasErrors = !!document.getElementsByClassName('ng-invalid')[0];
}
protected _openConfirmDialog() {
const dialogRef = this.#confirmationDialogService.openDialog({ disableConfirm: !this.valid });
return firstValueFrom(dialogRef.afterClosed());

View File

@ -0,0 +1,39 @@
<!--<div class="iqser-input-group" [ngClass]="classList" [class.datepicker-wrapper]="isDate">-->
<div class="iqser-input-group" [ngClass]="classList" [class.datepicker-wrapper]="isDate">
<label> {{label}} </label>
<ng-container *ngIf="isDate">
<input
[matDatepicker]="picker"
[placeholder]="placeholder || 'dd/mm/yy'"
[id]="id"
[name]="name"
[(ngModel)]="input"
(ngModelChange)="onChange($event)"
/>
<mat-datepicker-toggle [for]="picker" matSuffix>
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
</mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</ng-container>
<input
*ngIf="isText"
[(ngModel)]="input"
(ngModelChange)="onChange($event)"
[id]="id"
[name]="name"
[placeholder]="placeholder || ''"
type="text"
/>
<input
*ngIf="isNumber"
[(ngModel)]="input"
(ngModelChange)="onChange($event)"
[id]="id"
[name]="name"
type="number"
/>
</div>

View File

@ -0,0 +1,5 @@
.datepicker-wrapper {
.mat-datepicker-input {
width: 100%;
}
}

View File

@ -0,0 +1,65 @@
import { ChangeDetectionStrategy, Component, forwardRef, Input, OnInit, Optional, Self } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, ValidationErrors } from '@angular/forms';
import { FormFieldComponent } from '../form-field/form-field-component.directive';
const InputTypes = {
DATE: 'DATE',
NUMBER: 'NUMBER',
TEXT: 'TEXT',
IMAGE: 'IMAGE',
} as const;
export type InputType = keyof typeof InputTypes;
type DynamicInput = number | string | Date;
@Component({
selector: 'iqser-dynamic-input [label] [type]',
templateUrl: './dynamic-input.component.html',
styleUrls: ['./dynamic-input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: DynamicInputComponent,
},
{
provide: NG_VALIDATORS,
multi: true,
useExisting: DynamicInputComponent,
},
]
})
export class DynamicInputComponent extends FormFieldComponent<DynamicInput> {
@Input() label!: string;
@Input() type!: InputType;
@Input() placeholder?: string;
@Input() id?: string;
@Input() name?: string;
@Input() classList?: string = '';
@Input() input!: DynamicInput;
get isDate() {
return this.type === InputTypes.DATE;
}
get isNumber() {
return this.type === InputTypes.NUMBER;
}
get isText() {
return this.type === InputTypes.TEXT;
}
writeValue(input: DynamicInput): void {
this.input = input;
}
}

View File

@ -5,3 +5,4 @@ export * from './input-with-action/input-with-action.component';
export * from './details-radio/details-radio.component';
export * from './details-radio/details-radio-option';
export * from './form-field/form-field-component.directive';
export * from './dynamic-input/dynamic-input.component';

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IqserButtonsModule } from '../buttons';
import { RoundCheckboxComponent } from './round-checkbox/round-checkbox.component';
import { EditableInputComponent } from './editable-input/editable-input.component';
@ -8,13 +8,16 @@ import { InputWithActionComponent } from './input-with-action/input-with-action.
import { IqserIconsModule } from '../icons';
import { DetailsRadioComponent } from './details-radio/details-radio.component';
import { TranslateModule } from '@ngx-translate/core';
import { DynamicInputComponent } from './dynamic-input/dynamic-input.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
const modules = [IqserButtonsModule, FormsModule];
const components = [RoundCheckboxComponent, EditableInputComponent, InputWithActionComponent, DetailsRadioComponent];
const modules = [IqserButtonsModule, FormsModule, ReactiveFormsModule, MatDatepickerModule];
const components = [RoundCheckboxComponent, EditableInputComponent, InputWithActionComponent, DetailsRadioComponent, DynamicInputComponent];
@NgModule({
declarations: [...components],
exports: [...components],
imports: [CommonModule, IqserIconsModule, TranslateModule, ...modules],
imports: [CommonModule, IqserIconsModule, TranslateModule, ...modules, MatInputModule],
})
export class IqserInputsModule {}