diff --git a/src/assets/styles/common-inputs.scss b/src/assets/styles/common-inputs.scss
index 5a02c00..239e98a 100644
--- a/src/assets/styles/common-inputs.scss
+++ b/src/assets/styles/common-inputs.scss
@@ -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;
diff --git a/src/lib/dialog/base-dialog.component.ts b/src/lib/dialog/base-dialog.component.ts
index 13a500e..b3a867d 100644
--- a/src/lib/dialog/base-dialog.component.ts
+++ b/src/lib/dialog/base-dialog.component.ts
@@ -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());
diff --git a/src/lib/inputs/dynamic-input/dynamic-input.component.html b/src/lib/inputs/dynamic-input/dynamic-input.component.html
new file mode 100644
index 0000000..8b710c8
--- /dev/null
+++ b/src/lib/inputs/dynamic-input/dynamic-input.component.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/inputs/dynamic-input/dynamic-input.component.scss b/src/lib/inputs/dynamic-input/dynamic-input.component.scss
new file mode 100644
index 0000000..1c032f3
--- /dev/null
+++ b/src/lib/inputs/dynamic-input/dynamic-input.component.scss
@@ -0,0 +1,5 @@
+.datepicker-wrapper {
+ .mat-datepicker-input {
+ width: 100%;
+ }
+}
diff --git a/src/lib/inputs/dynamic-input/dynamic-input.component.ts b/src/lib/inputs/dynamic-input/dynamic-input.component.ts
new file mode 100644
index 0000000..3ed50a7
--- /dev/null
+++ b/src/lib/inputs/dynamic-input/dynamic-input.component.ts
@@ -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 {
+
+ @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;
+ }
+}
diff --git a/src/lib/inputs/index.ts b/src/lib/inputs/index.ts
index a7f132c..cd561f1 100644
--- a/src/lib/inputs/index.ts
+++ b/src/lib/inputs/index.ts
@@ -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';
diff --git a/src/lib/inputs/inputs.module.ts b/src/lib/inputs/inputs.module.ts
index 9cd024d..866e87f 100644
--- a/src/lib/inputs/inputs.module.ts
+++ b/src/lib/inputs/inputs.module.ts
@@ -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 {}