verben-ng-ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/ng-package.json +10 -0
- package/package.json +34 -0
- package/src/lib/Verbena-input/error.service.ts +23 -0
- package/src/lib/Verbena-input/verbena-input.component.css +59 -0
- package/src/lib/Verbena-input/verbena-input.component.html +64 -0
- package/src/lib/Verbena-input/verbena-input.component.spec.ts +25 -0
- package/src/lib/Verbena-input/verbena-input.component.ts +162 -0
- package/src/lib/Verbena-input/verbena-input.module.ts +12 -0
- package/src/lib/components/TemplateDirective.directive.ts +10 -0
- package/src/lib/components/card/card.component.css +20 -0
- package/src/lib/components/card/card.component.html +23 -0
- package/src/lib/components/card/card.component.spec.ts +23 -0
- package/src/lib/components/card/card.component.ts +33 -0
- package/src/lib/components/card/card.module.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.css +3 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.css +7 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view.component.css +39 -0
- package/src/lib/components/card-data-view/card-data-view.component.html +29 -0
- package/src/lib/components/card-data-view/card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view.component.ts +66 -0
- package/src/lib/components/card-data-view/card-data-view.module.ts +20 -0
- package/src/lib/components/card-data-view/card-data.ts +7 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.css +15 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.ts +19 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.css +0 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.ts +12 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.css +3 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.html +1 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.ts +10 -0
- package/src/lib/components/chip/ChipChangeEvent.ts +4 -0
- package/src/lib/components/chip/chip.component.css +94 -0
- package/src/lib/components/chip/chip.component.html +49 -0
- package/src/lib/components/chip/chip.component.spec.ts +23 -0
- package/src/lib/components/chip/chip.component.ts +209 -0
- package/src/lib/components/chip/chip.module.ts +24 -0
- package/src/lib/components/chip/documentation.md +26 -0
- package/src/lib/components/data-export/data-export.component.css +0 -0
- package/src/lib/components/data-export/data-export.component.html +90 -0
- package/src/lib/components/data-export/data-export.component.spec.ts +23 -0
- package/src/lib/components/data-export/data-export.component.ts +158 -0
- package/src/lib/components/data-export/data-export.module.ts +13 -0
- package/src/lib/components/data-export/data-export.service.spec.ts +16 -0
- package/src/lib/components/data-export/data-export.service.ts +152 -0
- package/src/lib/components/data-export/data-export.types.ts +21 -0
- package/src/lib/components/data-table/column.directive.spec.ts +8 -0
- package/src/lib/components/data-table/column.directive.ts +19 -0
- package/src/lib/components/data-table/data-table.component.css +0 -0
- package/src/lib/components/data-table/data-table.component.html +55 -0
- package/src/lib/components/data-table/data-table.component.spec.ts +21 -0
- package/src/lib/components/data-table/data-table.component.ts +336 -0
- package/src/lib/components/data-table/data-table.module.ts +11 -0
- package/src/lib/components/data-table/data-table.types.ts +13 -0
- package/src/lib/components/data-table/style.types.ts +55 -0
- package/src/lib/components/data-view/data-view-click-outside.directive.ts +44 -0
- package/src/lib/components/data-view/data-view.component.css +74 -0
- package/src/lib/components/data-view/data-view.component.html +161 -0
- package/src/lib/components/data-view/data-view.component.spec.ts +23 -0
- package/src/lib/components/data-view/data-view.component.ts +136 -0
- package/src/lib/components/data-view/data-view.module.ts +16 -0
- package/src/lib/components/date-picker/date-picker.component.css +65 -0
- package/src/lib/components/date-picker/date-picker.component.html +60 -0
- package/src/lib/components/date-picker/date-picker.component.specs.ts +23 -0
- package/src/lib/components/date-picker/date-picker.component.ts +143 -0
- package/src/lib/components/date-picker/date-picker.module.ts +12 -0
- package/src/lib/components/drop-down/DropdownChangeEvent.ts +4 -0
- package/src/lib/components/drop-down/DropdownLoadEvent.ts +19 -0
- package/src/lib/components/drop-down/DropdownMenuItem.ts +42 -0
- package/src/lib/components/drop-down/documentation.md +69 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.css +123 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.html +133 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.ts +88 -0
- package/src/lib/components/drop-down/drop-down.component.css +317 -0
- package/src/lib/components/drop-down/drop-down.component.html +177 -0
- package/src/lib/components/drop-down/drop-down.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down.component.ts +757 -0
- package/src/lib/components/drop-down/drop-down.module.ts +24 -0
- package/src/lib/components/image/image.component.css +12 -0
- package/src/lib/components/image/image.component.html +18 -0
- package/src/lib/components/image/image.component.spec.ts +23 -0
- package/src/lib/components/image/image.component.ts +45 -0
- package/src/lib/components/image/image.module.ts +11 -0
- package/src/lib/components/notification/notification.component.css +3 -0
- package/src/lib/components/notification/notification.component.html +19 -0
- package/src/lib/components/notification/notification.component.spec.ts +23 -0
- package/src/lib/components/notification/notification.component.ts +77 -0
- package/src/lib/components/notification/notification.module.ts +14 -0
- package/src/lib/components/shared.module.ts +9 -0
- package/src/lib/components/sort-table/sort-table.component.css +67 -0
- package/src/lib/components/sort-table/sort-table.component.html +164 -0
- package/src/lib/components/sort-table/sort-table.component.spec.ts +23 -0
- package/src/lib/components/sort-table/sort-table.component.ts +204 -0
- package/src/lib/components/sort-table/sort-table.module.ts +11 -0
- package/src/lib/components/svg/svg.component.css +0 -0
- package/src/lib/components/svg/svg.component.html +1 -0
- package/src/lib/components/svg/svg.component.spec.ts +23 -0
- package/src/lib/components/svg/svg.component.ts +64 -0
- package/src/lib/components/svg/svg.module.ts +10 -0
- package/src/lib/components/table-filter/table-filter.component.css +93 -0
- package/src/lib/components/table-filter/table-filter.component.html +293 -0
- package/src/lib/components/table-filter/table-filter.component.spec.ts +23 -0
- package/src/lib/components/table-filter/table-filter.component.ts +221 -0
- package/src/lib/components/table-filter/table-filter.module.ts +25 -0
- package/src/lib/components/tooltip/tooltip.component.css +8 -0
- package/src/lib/components/tooltip/tooltip.component.html +13 -0
- package/src/lib/components/tooltip/tooltip.component.spec.ts +23 -0
- package/src/lib/components/tooltip/tooltip.component.ts +84 -0
- package/src/lib/components/tooltip/tooltip.module.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.config.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.css +71 -0
- package/src/lib/components/verben-mail/verben-mail.component.html +139 -0
- package/src/lib/components/verben-mail/verben-mail.component.ts +151 -0
- package/src/lib/components/verben-mail/verben-mail.module.ts +18 -0
- package/src/lib/components/visible-column/visible-column.component.css +83 -0
- package/src/lib/components/visible-column/visible-column.component.html +77 -0
- package/src/lib/components/visible-column/visible-column.component.spec.ts +23 -0
- package/src/lib/components/visible-column/visible-column.component.ts +106 -0
- package/src/lib/components/visible-column/visible-column.module.ts +11 -0
- package/src/lib/config.ts +37 -0
- package/src/lib/control-options/control-options.directive.ts +129 -0
- package/src/lib/control-options/control-options.module.ts +10 -0
- package/src/lib/convert-to-integer/convert-to-integer.directive.ts +28 -0
- package/src/lib/convert-to-integer/convert-to-integer.module.ts +10 -0
- package/src/lib/convert-to-integer/public-api.ts +1 -0
- package/src/lib/convert-to-number/convert-to-number.directive.ts +22 -0
- package/src/lib/convert-to-number/convert-to-number.module.ts +8 -0
- package/src/lib/convert-to-number/public-api.ts +1 -0
- package/src/lib/email-validator/email-validator.directive.ts +24 -0
- package/src/lib/email-validator/email-validator.module.ts +14 -0
- package/src/lib/models/column-filter.ts +5 -0
- package/src/lib/models/data-filter.ts +8 -0
- package/src/lib/models/mail-model.ts +8 -0
- package/src/lib/models/sort-filter.ts +0 -0
- package/src/lib/models/table-filter.ts +34 -0
- package/src/lib/number-range/number-range.directive.ts +35 -0
- package/src/lib/number-range/number-range.module.ts +11 -0
- package/src/lib/phone-number/phone-number.directive.ts +22 -0
- package/src/lib/phone-number/phone-number.module.ts +10 -0
- package/src/lib/phone-number/public-api.ts +1 -0
- package/src/lib/required-input/required-input.directive.ts +18 -0
- package/src/lib/required-input/required-input.module.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.spec.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.ts +70 -0
- package/src/lib/theme-switcher/theme-switcher.module.ts +8 -0
- package/src/lib/validate/error-message.service.ts +104 -0
- package/src/lib/validate/validate.directive.ts +110 -0
- package/src/lib/validate/validate.module.ts +17 -0
- package/src/lib/validate-input/validate-input.directive.ts +8 -0
- package/src/lib/validate-input/validate-input.module.ts +8 -0
- package/src/lib/verben-ng-ui.component.spec.ts +23 -0
- package/src/lib/verben-ng-ui.component.ts +16 -0
- package/src/lib/verben-ng-ui.service.spec.ts +16 -0
- package/src/lib/verben-ng-ui.service.ts +9 -0
- package/src/lib/verbena-badge/verbena-badge.component.css +16 -0
- package/src/lib/verbena-badge/verbena-badge.component.html +13 -0
- package/src/lib/verbena-badge/verbena-badge.component.spec.ts +25 -0
- package/src/lib/verbena-badge/verbena-badge.component.ts +18 -0
- package/src/lib/verbena-badge/verbena-badge.module.ts +10 -0
- package/src/lib/verbena-button/verbena-button.component.css +20 -0
- package/src/lib/verbena-button/verbena-button.component.html +25 -0
- package/src/lib/verbena-button/verbena-button.component.spec.ts +25 -0
- package/src/lib/verbena-button/verbena-button.component.ts +92 -0
- package/src/lib/verbena-button/verbena-button.module.ts +11 -0
- package/src/lib/verbena-switch/verbena-switch.component.css +45 -0
- package/src/lib/verbena-switch/verbena-switch.component.html +8 -0
- package/src/lib/verbena-switch/verbena-switch.component.spec.ts +25 -0
- package/src/lib/verbena-switch/verbena-switch.component.ts +31 -0
- package/src/lib/verbena-switch/verbena-switch.module.ts +10 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.css +0 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.html +19 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.spec.ts +33 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.ts +44 -0
- package/src/lib/verbena-textarea/verbena-textarea.module.ts +11 -0
- package/src/public-api.ts +122 -0
- package/src/styles.css +103 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +15 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
3
|
+
import { MailPayload } from '../../models/mail-model';
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'verben-mail-template',
|
|
7
|
+
templateUrl: './verben-mail.component.html',
|
|
8
|
+
styleUrls: ['./verben-mail.component.css'],
|
|
9
|
+
})
|
|
10
|
+
export class VerbenMailTemplate {
|
|
11
|
+
@Input() containerWidth: string = '500px';
|
|
12
|
+
@Input() borderRadius: string = '10px';
|
|
13
|
+
@Input() primaryColor: string = '#FFE681';
|
|
14
|
+
@Input() secondaryColor: string = '';
|
|
15
|
+
@Input() tetiaryColor: string = '';
|
|
16
|
+
@Input() border: string = '1px solid gray';
|
|
17
|
+
@Input() pd: string = '20px';
|
|
18
|
+
@Input() m: string = '';
|
|
19
|
+
@Input() max: number = 10;
|
|
20
|
+
mailForm: FormGroup;
|
|
21
|
+
isRichText: boolean = false;
|
|
22
|
+
isUploading: boolean = false;
|
|
23
|
+
uploadedFileName: string | null = null;
|
|
24
|
+
fileUploadError: string | null = null;
|
|
25
|
+
toEmails: string[] = [];
|
|
26
|
+
ccEmails: string[] = [];
|
|
27
|
+
bccEmails: string[] = [];
|
|
28
|
+
toEmailInput: string = '';
|
|
29
|
+
ccEmailInput: string = '';
|
|
30
|
+
bccEmailInput: string = '';
|
|
31
|
+
mailData: any;
|
|
32
|
+
toEmailError: string | null = null;
|
|
33
|
+
ccEmailError: string | null = null;
|
|
34
|
+
bccEmailError: string | null = null;
|
|
35
|
+
@Output() mailPayload = new EventEmitter<MailPayload>();
|
|
36
|
+
constructor(private fb: FormBuilder) {
|
|
37
|
+
this.mailForm = this.fb.group({
|
|
38
|
+
subject: ['', Validators.required],
|
|
39
|
+
body: ['', Validators.required],
|
|
40
|
+
toEmails: [[], Validators.required],
|
|
41
|
+
ccEmails: [[]],
|
|
42
|
+
bccEmails: [[]],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
onToChange(): void {
|
|
47
|
+
const newValues = this.mailForm.get('toEmails')?.value || [];
|
|
48
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
49
|
+
const validEmails: string[] = [];
|
|
50
|
+
|
|
51
|
+
newValues.forEach((email: string) => {
|
|
52
|
+
if (emailRegex.test(email)) {
|
|
53
|
+
validEmails.push(email);
|
|
54
|
+
} else {
|
|
55
|
+
if (!emailRegex.test(email)) {
|
|
56
|
+
this.toEmailError = 'email must be valid';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (validEmails.length === 0) {
|
|
61
|
+
this.toEmailError = 'email must be valid';
|
|
62
|
+
} else {
|
|
63
|
+
this.toEmailError = '';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.toEmails = validEmails;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
onCcChange(): void {
|
|
70
|
+
const newValues = this.mailForm.get('ccEmails')?.value||[];
|
|
71
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
72
|
+
const validEmails = newValues.filter((email: string) =>
|
|
73
|
+
emailRegex.test(email)
|
|
74
|
+
);
|
|
75
|
+
this.ccEmails = validEmails;
|
|
76
|
+
}
|
|
77
|
+
onBccChange(): void {
|
|
78
|
+
const newValues = this.mailForm.get('bccEmails')?.value||[];
|
|
79
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
80
|
+
const validEmails = newValues.filter((email: string) =>
|
|
81
|
+
emailRegex.test(email)
|
|
82
|
+
);
|
|
83
|
+
this.bccEmails = validEmails;
|
|
84
|
+
}
|
|
85
|
+
validateEmail(email: string): boolean {
|
|
86
|
+
const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
|
|
87
|
+
return emailRegex.test(email);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onFileSelected(event: Event) {
|
|
91
|
+
const input = event.target as HTMLInputElement;
|
|
92
|
+
if (input.files && input.files.length > 0) {
|
|
93
|
+
const file = input.files[0];
|
|
94
|
+
this.fileUploadError = null;
|
|
95
|
+
if (!file) {
|
|
96
|
+
this.isUploading = true;
|
|
97
|
+
}
|
|
98
|
+
if (file.size > 5000000) {
|
|
99
|
+
this.fileUploadError = 'File size exceeds 5MB limit.';
|
|
100
|
+
this.uploadedFileName = null;
|
|
101
|
+
this.isUploading = false; // Reset isUploading state
|
|
102
|
+
} else {
|
|
103
|
+
this.uploadedFileName = file.name;
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
this.isUploading = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
removeFile() {
|
|
111
|
+
this.uploadedFileName = null;
|
|
112
|
+
this.fileUploadError = null;
|
|
113
|
+
const fileInput = document.getElementById('attachment') as HTMLInputElement;
|
|
114
|
+
if (fileInput) {
|
|
115
|
+
fileInput.value = '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
toggleEditor() {
|
|
120
|
+
this.isRichText = !this.isRichText;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
sendEmail() {
|
|
124
|
+
if (this.mailForm.valid) {
|
|
125
|
+
const emailData: MailPayload = {
|
|
126
|
+
subject: this.mailForm.value.subject,
|
|
127
|
+
body: this.mailForm.value.body,
|
|
128
|
+
to: this.mailForm.get('toEmails')?.value,
|
|
129
|
+
cc: this.mailForm.get('ccEmails')?.value,
|
|
130
|
+
bcc: this.mailForm.get('bccEmails')?.value,
|
|
131
|
+
attachment: this.uploadedFileName,
|
|
132
|
+
};
|
|
133
|
+
this.mailPayload.emit(emailData);
|
|
134
|
+
this.resetForm();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
resetForm() {
|
|
138
|
+
this.mailForm.get('toEmails')?.reset('');
|
|
139
|
+
this.mailForm.get('ccEmails')?.reset('');
|
|
140
|
+
this.mailForm.get('bccEmails')?.reset('');
|
|
141
|
+
this.mailForm.get("subject")?.reset('')
|
|
142
|
+
this.mailForm.get("body")?.reset('')
|
|
143
|
+
this.toEmailError = null;
|
|
144
|
+
this.ccEmailError = null;
|
|
145
|
+
this.bccEmailError = null;
|
|
146
|
+
this.uploadedFileName = null;
|
|
147
|
+
this.fileUploadError = null;
|
|
148
|
+
this.isUploading = false;
|
|
149
|
+
this.isRichText = false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { VerbenMailTemplate } from './verben-mail.component';
|
|
5
|
+
import { ChipModule } from '../chip/chip.module';
|
|
6
|
+
import { SvgModule } from '../svg/svg.module';
|
|
7
|
+
@NgModule({
|
|
8
|
+
declarations: [VerbenMailTemplate],
|
|
9
|
+
imports: [
|
|
10
|
+
FormsModule,
|
|
11
|
+
CommonModule,
|
|
12
|
+
ChipModule,
|
|
13
|
+
ReactiveFormsModule,
|
|
14
|
+
SvgModule,
|
|
15
|
+
],
|
|
16
|
+
exports: [VerbenMailTemplate],
|
|
17
|
+
})
|
|
18
|
+
export class VerbenaMailTemplateModule {}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
|
|
2
|
+
hr{
|
|
3
|
+
border: 1px solid rgba(232, 234, 241, 1);
|
|
4
|
+
margin:0.8rem 0rem;
|
|
5
|
+
}
|
|
6
|
+
.flex{
|
|
7
|
+
display: flex;
|
|
8
|
+
}
|
|
9
|
+
.justify-between{
|
|
10
|
+
justify-content: space-between;
|
|
11
|
+
}
|
|
12
|
+
.items-center{
|
|
13
|
+
align-items: center;
|
|
14
|
+
}
|
|
15
|
+
.font-semibold{
|
|
16
|
+
font-weight: 600;
|
|
17
|
+
}
|
|
18
|
+
.font-semibold{
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
}
|
|
21
|
+
.font-normal{
|
|
22
|
+
font-weight: 400;
|
|
23
|
+
}
|
|
24
|
+
.text-sm{
|
|
25
|
+
font-size: 13px;
|
|
26
|
+
}
|
|
27
|
+
.gap{
|
|
28
|
+
gap: 10px;
|
|
29
|
+
}
|
|
30
|
+
.gap-sm{
|
|
31
|
+
gap: 2px;
|
|
32
|
+
}
|
|
33
|
+
.gap-md{
|
|
34
|
+
gap: 6px;
|
|
35
|
+
}
|
|
36
|
+
.cursor-pointer{
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
}
|
|
39
|
+
.cursor-not-allowed{
|
|
40
|
+
cursor: not-allowed;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.visible-column-header {
|
|
44
|
+
margin-bottom: 10px;
|
|
45
|
+
padding: 10px 0px 10px 0px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.column-title {
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
font-size: 14px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.column-title sup {
|
|
54
|
+
color: #3479e9;
|
|
55
|
+
font-weight: 600;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.column-reset {
|
|
59
|
+
color: #3479e9;
|
|
60
|
+
font-size: 13px;
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.btn-wrapper{
|
|
66
|
+
display: flex;
|
|
67
|
+
justify-content: end;
|
|
68
|
+
}
|
|
69
|
+
.disabledBtn {
|
|
70
|
+
cursor: not-allowed;
|
|
71
|
+
}
|
|
72
|
+
.enabledBtn {
|
|
73
|
+
cursor:pointer;
|
|
74
|
+
}
|
|
75
|
+
.show-more {
|
|
76
|
+
font-size: 12px;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
padding: 16px 0;
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 2px;
|
|
82
|
+
color: gray;
|
|
83
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<div
|
|
2
|
+
[style.background-color]="bgColor"
|
|
3
|
+
[style.box-shadow]="boxShadow"
|
|
4
|
+
[style.border]="border"
|
|
5
|
+
[style.border-radius]="borderRadius"
|
|
6
|
+
[style.color]="textColor"
|
|
7
|
+
[style.width]="width"
|
|
8
|
+
[style.height]="height"
|
|
9
|
+
[style.padding]="pd"
|
|
10
|
+
class="column-control"
|
|
11
|
+
>
|
|
12
|
+
<div class="visible-column-header flex justify-between text-sm">
|
|
13
|
+
<span class="column-title">
|
|
14
|
+
Column <sup>[{{ getSelectedColumnCount() }}]</sup>
|
|
15
|
+
</span>
|
|
16
|
+
<span class="column-reset" (click)="resetColumns()">Reset</span>
|
|
17
|
+
</div>
|
|
18
|
+
<hr />
|
|
19
|
+
|
|
20
|
+
<!-- Select All Checkbox -->
|
|
21
|
+
<div class="flex items-center gap" [style.padding]="'4px 10px'">
|
|
22
|
+
<label [style.font-size]="'13px'" [style.font-weight]="'500'">
|
|
23
|
+
<input type="checkbox" [checked]="selectAll" (change)="toggleSelectAll()" />
|
|
24
|
+
Select All
|
|
25
|
+
</label>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<!-- Columns List -->
|
|
29
|
+
<ul *ngFor="let column of columns; let i = index" class="column-options-container">
|
|
30
|
+
<li
|
|
31
|
+
[attr.draggable]="enableDragAndDrop"
|
|
32
|
+
(dragstart)="onDragStart(i, $event)"
|
|
33
|
+
(dragover)="onDragOver($event)"
|
|
34
|
+
(drop)="onDrop(i, $event)"
|
|
35
|
+
*ngIf="i < displayedColumns"
|
|
36
|
+
[style.font-size]="'14px'"
|
|
37
|
+
[style.margin-top]="'14px'"
|
|
38
|
+
class="flex gap-sm items-center"
|
|
39
|
+
>
|
|
40
|
+
<verben-svg *ngIf="enableDragAndDrop" fill="black" class="svg" icon="square-dot"></verben-svg>
|
|
41
|
+
<label class="flex gap-md items-center">
|
|
42
|
+
<input type="checkbox" [(ngModel)]="visibleColumns[i]" (ngModelChange)="updateSelectAllStatus()" />
|
|
43
|
+
{{ column.name }}
|
|
44
|
+
</label>
|
|
45
|
+
</li>
|
|
46
|
+
</ul>
|
|
47
|
+
|
|
48
|
+
<!-- Show More / Show Less -->
|
|
49
|
+
<div *ngIf="displayedColumns <= columns.length" class="cursor-pointer" [style.padding]="'20px 10px 0px 10px'">
|
|
50
|
+
<span (click)="toggleShowMore()">
|
|
51
|
+
{{ displayedColumns === columns.length ? "Show Less" : "Show More" }}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
<hr />
|
|
55
|
+
|
|
56
|
+
<!-- Save Button -->
|
|
57
|
+
<div class="btn-wrapper">
|
|
58
|
+
<button
|
|
59
|
+
[style.margin-top]="'0.5rem'"
|
|
60
|
+
[style.outline]="'none'"
|
|
61
|
+
[style.border]="'none'"
|
|
62
|
+
[style.padding]="'0.2rem 1.6rem'"
|
|
63
|
+
[style.background-color]="primaryColor"
|
|
64
|
+
[style.color]="tertiaryColor"
|
|
65
|
+
[style.font-size]="'12px'"
|
|
66
|
+
[style.font-weight]="'600'"
|
|
67
|
+
[disabled]="getSelectedColumnCount() === 0"
|
|
68
|
+
[ngClass]="{
|
|
69
|
+
disabledBtn: getSelectedColumnCount() === 0,
|
|
70
|
+
enableBtn: getSelectedColumnCount() !== 0
|
|
71
|
+
}"
|
|
72
|
+
(click)="saveColumnVisibility()"
|
|
73
|
+
>
|
|
74
|
+
Save
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { VisibleColumnComponent } from './visible-column.component';
|
|
4
|
+
|
|
5
|
+
describe('VisibleColumnComponent', () => {
|
|
6
|
+
let component: VisibleColumnComponent;
|
|
7
|
+
let fixture: ComponentFixture<VisibleColumnComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
declarations: [VisibleColumnComponent]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(VisibleColumnComponent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { IDataFilter } from '../../models/data-filter';
|
|
3
|
+
|
|
4
|
+
interface Item {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'verben-visible-column',
|
|
10
|
+
templateUrl: './visible-column.component.html',
|
|
11
|
+
styleUrls: ['./visible-column.component.css'],
|
|
12
|
+
})
|
|
13
|
+
export class VisibleColumnComponent {
|
|
14
|
+
@Input() columns: IDataFilter[] = [];
|
|
15
|
+
@Input() items: Item[] = [];
|
|
16
|
+
@Input() enableDragAndDrop: boolean = true;
|
|
17
|
+
@Input() displayedColumns: number = 5;
|
|
18
|
+
@Input() showMore: boolean = false;
|
|
19
|
+
@Input() pd?: string;
|
|
20
|
+
@Input() mg?: string;
|
|
21
|
+
@Input() height?: string;
|
|
22
|
+
@Input() width?: string;
|
|
23
|
+
@Input() bgColor?: string;
|
|
24
|
+
@Input() boxShadow?: string;
|
|
25
|
+
@Input() textColor?: string;
|
|
26
|
+
@Input() primaryColor?: string;
|
|
27
|
+
@Input() secondaryColor?: string;
|
|
28
|
+
@Input() tertiaryColor?: string;
|
|
29
|
+
@Input() border?: string;
|
|
30
|
+
@Input() borderRadius?: string;
|
|
31
|
+
@Input() selectWidth?: string;
|
|
32
|
+
@Output() columnsUpdated = new EventEmitter<IDataFilter[]>();
|
|
33
|
+
|
|
34
|
+
originalColumnOrder: IDataFilter[] = [];
|
|
35
|
+
visibleColumns: boolean[] = [];
|
|
36
|
+
draggedIndex: number | null = null;
|
|
37
|
+
selectAll: boolean = false;
|
|
38
|
+
|
|
39
|
+
ngOnInit() {
|
|
40
|
+
this.originalColumnOrder = [...this.columns];
|
|
41
|
+
this.initializeColumnVisibility();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private initializeColumnVisibility() {
|
|
45
|
+
this.visibleColumns = this.columns.map((column) => column.checked);
|
|
46
|
+
this.updateSelectAllStatus();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
resetColumns() {
|
|
50
|
+
// Reset columns to the original order
|
|
51
|
+
this.columns = JSON.parse(JSON.stringify(this.originalColumnOrder)); // Ensure it's a deep copy
|
|
52
|
+
this.initializeColumnVisibility();
|
|
53
|
+
this.selectAll = false; // Reset select all
|
|
54
|
+
this.updateSelectAllStatus();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getSelectedColumnCount(): number {
|
|
58
|
+
return this.visibleColumns.filter((isVisible) => isVisible).length;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
saveColumnVisibility() {
|
|
62
|
+
this.columns.forEach((column, index) => {
|
|
63
|
+
column.checked = this.visibleColumns[index];
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const selectedColumns = this.columns.filter(column => column.checked);
|
|
67
|
+
this.columnsUpdated.emit(selectedColumns);
|
|
68
|
+
console.log(selectedColumns);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
toggleShowMore() {
|
|
72
|
+
this.showMore = !this.showMore;
|
|
73
|
+
this.displayedColumns = this.showMore ? this.columns.length : 5;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
toggleSelectAll() {
|
|
77
|
+
this.selectAll = !this.selectAll;
|
|
78
|
+
this.visibleColumns = this.visibleColumns.map(() => this.selectAll);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
updateSelectAllStatus() {
|
|
82
|
+
this.selectAll = this.visibleColumns.every(isVisible => isVisible);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onDragStart(index: number, event: DragEvent) {
|
|
86
|
+
this.draggedIndex = index;
|
|
87
|
+
event.dataTransfer?.setData('text/plain', String(index));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
onDragOver(event: DragEvent) {
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
onDrop(index: number, event: DragEvent) {
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
if (this.draggedIndex !== null && this.draggedIndex !== index) {
|
|
97
|
+
this.swapColumns(this.draggedIndex, index);
|
|
98
|
+
}
|
|
99
|
+
this.draggedIndex = null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private swapColumns(fromIndex: number, toIndex: number) {
|
|
103
|
+
[this.columns[fromIndex], this.columns[toIndex]] = [this.columns[toIndex], this.columns[fromIndex]];
|
|
104
|
+
[this.visibleColumns[fromIndex], this.visibleColumns[toIndex]] = [this.visibleColumns[toIndex], this.visibleColumns[fromIndex]];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { FormsModule } from '@angular/forms'
|
|
3
|
+
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { VisibleColumnComponent } from './visible-column.component';
|
|
5
|
+
import { SvgModule } from '../svg/svg.module';
|
|
6
|
+
@NgModule({
|
|
7
|
+
declarations:[VisibleColumnComponent],
|
|
8
|
+
imports: [CommonModule, FormsModule,SvgModule],
|
|
9
|
+
exports: [VisibleColumnComponent]
|
|
10
|
+
})
|
|
11
|
+
export class VisibleColumnModule {}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ConditionalOptions, DataFilterType, ITypeOption } from "./models/table-filter";
|
|
2
|
+
|
|
3
|
+
export class Config {
|
|
4
|
+
typeOptions: ITypeOption[] = [
|
|
5
|
+
{
|
|
6
|
+
type: DataFilterType.String,
|
|
7
|
+
options: [ConditionalOptions.Equal,ConditionalOptions.NotEqual]
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
type: DataFilterType.Integer,
|
|
11
|
+
options: [ConditionalOptions.Equal, ConditionalOptions.LessThan, ConditionalOptions.GreaterThan]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: DataFilterType.Decimal,
|
|
15
|
+
options: [ConditionalOptions.Equal, ConditionalOptions.LessThan, ConditionalOptions.GreaterThan]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: DataFilterType.Credit,
|
|
19
|
+
options: [ConditionalOptions.Equal, ConditionalOptions.LessThan, ConditionalOptions.GreaterThan]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: DataFilterType.Date,
|
|
23
|
+
options: [ConditionalOptions.On,ConditionalOptions.Before,ConditionalOptions.After]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: DataFilterType.Bool,
|
|
27
|
+
options: [ConditionalOptions.Yes,ConditionalOptions.No]
|
|
28
|
+
}
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
getConditionOptions(filterType: DataFilterType): string[] | null {
|
|
32
|
+
const typeOption = this.typeOptions.find(option => option.type === filterType);
|
|
33
|
+
return typeOption ? typeOption.options : null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Directive, ElementRef, Input, OnChanges, Renderer2, SimpleChanges } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[controlOptions]'
|
|
5
|
+
})
|
|
6
|
+
export class ControlOptionsDirective implements OnChanges {
|
|
7
|
+
|
|
8
|
+
// Inputs for various control options
|
|
9
|
+
@Input() hidden: boolean = false;
|
|
10
|
+
@Input() disabled: boolean = false;
|
|
11
|
+
@Input() height: string | null = null;
|
|
12
|
+
@Input() width: string | null = null;
|
|
13
|
+
@Input() minHeight: string | null = null;
|
|
14
|
+
@Input() minWidth: string | null = null;
|
|
15
|
+
@Input() maxHeight: string | null = null;
|
|
16
|
+
@Input() maxWidth: string | null = null;
|
|
17
|
+
@Input() position: 'center' | 'left' | 'right' | 'top' | 'bottom' | null = null;
|
|
18
|
+
@Input() scrollable: boolean = false;
|
|
19
|
+
@Input() singleLine: boolean = false;
|
|
20
|
+
@Input() multiLine: boolean = false;
|
|
21
|
+
@Input() border: string | null = null;
|
|
22
|
+
@Input() borderRadius: string | null = null;
|
|
23
|
+
@Input() textColor: string | null = null;
|
|
24
|
+
@Input() backgroundColor: string | null = null;
|
|
25
|
+
@Input() hoverStyles: { [key: string]: string } | null = null;
|
|
26
|
+
|
|
27
|
+
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
|
28
|
+
|
|
29
|
+
ngOnChanges(changes: SimpleChanges): void {
|
|
30
|
+
this.applyStyles();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private applyStyles(): void {
|
|
34
|
+
const nativeElement = this.el.nativeElement;
|
|
35
|
+
|
|
36
|
+
// Handle hidden property
|
|
37
|
+
this.renderer.setStyle(nativeElement, 'display', this.hidden ? 'none' : 'block');
|
|
38
|
+
|
|
39
|
+
// Handle disabled property
|
|
40
|
+
if (this.disabled) {
|
|
41
|
+
this.renderer.setAttribute(nativeElement, 'disabled', 'true');
|
|
42
|
+
this.renderer.setStyle(nativeElement, 'pointer-events', 'none');
|
|
43
|
+
this.renderer.setStyle(nativeElement, 'opacity', '0.6');
|
|
44
|
+
} else {
|
|
45
|
+
this.renderer.removeAttribute(nativeElement, 'disabled');
|
|
46
|
+
this.renderer.setStyle(nativeElement, 'pointer-events', 'auto');
|
|
47
|
+
this.renderer.setStyle(nativeElement, 'opacity', '1');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Apply height, width, min/max constraints
|
|
51
|
+
this.applyDimension(nativeElement, 'height', this.height);
|
|
52
|
+
this.applyDimension(nativeElement, 'width', this.width);
|
|
53
|
+
this.applyDimension(nativeElement, 'min-height', this.minHeight);
|
|
54
|
+
this.applyDimension(nativeElement, 'min-width', this.minWidth);
|
|
55
|
+
this.applyDimension(nativeElement, 'max-height', this.maxHeight);
|
|
56
|
+
this.applyDimension(nativeElement, 'max-width', this.maxWidth);
|
|
57
|
+
|
|
58
|
+
// Handle position
|
|
59
|
+
this.handlePosition();
|
|
60
|
+
|
|
61
|
+
// Scrollable property
|
|
62
|
+
this.renderer.setStyle(nativeElement, 'overflow', this.scrollable ? 'auto' : 'hidden');
|
|
63
|
+
|
|
64
|
+
// Single-line or multi-line
|
|
65
|
+
if (this.singleLine) {
|
|
66
|
+
this.renderer.setStyle(nativeElement, 'white-space', 'nowrap');
|
|
67
|
+
} else if (this.multiLine) {
|
|
68
|
+
this.renderer.setStyle(nativeElement, 'white-space', 'normal');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Apply border and border-radius
|
|
72
|
+
this.applyStyle(nativeElement, 'border', this.border);
|
|
73
|
+
this.applyStyle(nativeElement, 'border-radius', this.borderRadius);
|
|
74
|
+
|
|
75
|
+
// Apply text color and background color
|
|
76
|
+
this.applyStyle(nativeElement, 'color', this.textColor);
|
|
77
|
+
this.applyStyle(nativeElement, 'background-color', this.backgroundColor);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Helper function to apply height, width, and similar styles
|
|
81
|
+
private applyDimension(element: any, style: string, value: string | null): void {
|
|
82
|
+
if (value) {
|
|
83
|
+
this.renderer.setStyle(element, style, value);
|
|
84
|
+
} else {
|
|
85
|
+
this.renderer.removeStyle(element, style);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Generalized style application
|
|
90
|
+
private applyStyle(element: any, style: string, value: string | null): void {
|
|
91
|
+
if (value) {
|
|
92
|
+
this.renderer.setStyle(element, style, value);
|
|
93
|
+
} else {
|
|
94
|
+
this.renderer.removeStyle(element, style);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Handle position based on the input
|
|
99
|
+
private handlePosition(): void {
|
|
100
|
+
const nativeElement = this.el.nativeElement;
|
|
101
|
+
|
|
102
|
+
switch (this.position) {
|
|
103
|
+
case 'center':
|
|
104
|
+
this.renderer.setStyle(nativeElement, 'position', 'absolute');
|
|
105
|
+
this.renderer.setStyle(nativeElement, 'top', '50%');
|
|
106
|
+
this.renderer.setStyle(nativeElement, 'left', '50%');
|
|
107
|
+
this.renderer.setStyle(nativeElement, 'transform', 'translate(-50%, -50%)');
|
|
108
|
+
break;
|
|
109
|
+
case 'left':
|
|
110
|
+
this.renderer.setStyle(nativeElement, 'position', 'absolute');
|
|
111
|
+
this.renderer.setStyle(nativeElement, 'left', '0');
|
|
112
|
+
break;
|
|
113
|
+
case 'right':
|
|
114
|
+
this.renderer.setStyle(nativeElement, 'position', 'absolute');
|
|
115
|
+
this.renderer.setStyle(nativeElement, 'right', '0');
|
|
116
|
+
break;
|
|
117
|
+
case 'top':
|
|
118
|
+
this.renderer.setStyle(nativeElement, 'position', 'absolute');
|
|
119
|
+
this.renderer.setStyle(nativeElement, 'top', '0');
|
|
120
|
+
break;
|
|
121
|
+
case 'bottom':
|
|
122
|
+
this.renderer.setStyle(nativeElement, 'position', 'absolute');
|
|
123
|
+
this.renderer.setStyle(nativeElement, 'bottom', '0');
|
|
124
|
+
break;
|
|
125
|
+
default:
|
|
126
|
+
this.renderer.setStyle(nativeElement, 'position', 'static');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { ControlOptionsDirective } from './control-options.directive';
|
|
4
|
+
|
|
5
|
+
@NgModule({
|
|
6
|
+
declarations: [ControlOptionsDirective],
|
|
7
|
+
imports: [CommonModule],
|
|
8
|
+
exports: [ControlOptionsDirective]
|
|
9
|
+
})
|
|
10
|
+
export class ControlOptionsModule {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appConvertToInteger]'
|
|
5
|
+
})
|
|
6
|
+
export class ConvertToIntegerDirective {
|
|
7
|
+
|
|
8
|
+
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
|
9
|
+
|
|
10
|
+
@HostListener('input', ['$event'])
|
|
11
|
+
onInputChange(event: Event): void {
|
|
12
|
+
const inputValue = (event.target as HTMLInputElement).value;
|
|
13
|
+
const integerValue = this.formatToInteger(inputValue);
|
|
14
|
+
this.renderer.setProperty(this.el.nativeElement, 'value', integerValue);
|
|
15
|
+
console.log(`this is ${integerValue}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private formatToInteger(value: string): string {
|
|
19
|
+
if (!value) {
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
const numericValue = parseInt(value, 10);
|
|
23
|
+
if (isNaN(numericValue)) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
return numericValue.toString();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { ConvertToIntegerDirective } from './convert-to-integer.directive';
|
|
4
|
+
|
|
5
|
+
@NgModule({
|
|
6
|
+
declarations: [ConvertToIntegerDirective],
|
|
7
|
+
imports: [CommonModule],
|
|
8
|
+
exports: [ConvertToIntegerDirective]
|
|
9
|
+
})
|
|
10
|
+
export class ConvertToIntegerModule {}
|