quang 20.1.8 → 20.2.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/components/autocomplete/README.md +71 -54
- package/components/checkbox/README.md +50 -40
- package/components/date/README.md +481 -23
- package/components/input/README.md +150 -26
- package/components/input/index.d.ts +7 -1
- package/components/paginator/README.md +51 -27
- package/components/select/README.md +18 -28
- package/components/table/README.md +202 -26
- package/components/wysiwyg/README.md +11 -23
- package/fesm2022/quang-components-input.mjs +13 -4
- package/fesm2022/quang-components-input.mjs.map +1 -1
- package/fesm2022/quang-components-shared.mjs +16 -18
- package/fesm2022/quang-components-shared.mjs.map +1 -1
- package/fesm2022/quang-overlay-modal.mjs +125 -2
- package/fesm2022/quang-overlay-modal.mjs.map +1 -1
- package/fesm2022/quang-overlay-shared.mjs +13 -15
- package/fesm2022/quang-overlay-shared.mjs.map +1 -1
- package/overlay/modal/index.d.ts +34 -3
- package/overlay/shared/index.d.ts +6 -6
- package/package.json +29 -29
|
@@ -4,35 +4,103 @@ The `QuangInputComponent` must be configured using the `componentType` input pro
|
|
|
4
4
|
|
|
5
5
|
## Supported Types
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
7
|
+
The component supports the following input types, each with specific behaviors and configurations:
|
|
8
|
+
|
|
9
|
+
### Text Input Types
|
|
10
|
+
|
|
11
|
+
- **text** — Standard text input for general text entry
|
|
12
|
+
- **email** — Email input with built-in email validation
|
|
13
|
+
- **password** — Password input with optional show/hide toggle functionality
|
|
14
|
+
- **url** — URL input with URL format validation
|
|
15
|
+
- **search** — Search input with native search behavior
|
|
16
|
+
- **tel** — Telephone number input
|
|
17
|
+
|
|
18
|
+
### Numeric Input Types
|
|
19
|
+
|
|
20
|
+
- **number** — Numeric input with step controls and min/max validation
|
|
21
|
+
|
|
22
|
+
### Special Input Types
|
|
23
|
+
|
|
24
|
+
- **textarea** — Multi-line text input with resizable functionality
|
|
25
|
+
- **color** — Color picker input
|
|
26
|
+
|
|
27
|
+
### Type-Specific Features
|
|
28
|
+
|
|
29
|
+
#### Textarea (`componentType="textarea"`)
|
|
30
|
+
|
|
31
|
+
- **Multi-line support**: Automatically expands for content
|
|
32
|
+
- **Resizable control**: Use `resizable` input to enable/disable manual resizing
|
|
33
|
+
- **No min/max number constraints**: Number-related inputs are ignored
|
|
34
|
+
|
|
35
|
+
#### Password (`componentType="password"`)
|
|
36
|
+
|
|
37
|
+
- **Toggle visibility**: Built-in show/hide password functionality
|
|
38
|
+
- **Icon support**: Custom icons through content projection
|
|
39
|
+
- **Security**: Masks input by default, reveals on toggle
|
|
40
|
+
|
|
41
|
+
#### Number (`componentType="number"`)
|
|
42
|
+
|
|
43
|
+
- **Step controls**: Use `componentStep` to define increment/decrement values
|
|
44
|
+
- **Range validation**: Set `minNumber` and `maxNumber` for value constraints
|
|
45
|
+
- **Decimal support**: Supports decimal values when step allows
|
|
46
|
+
|
|
47
|
+
#### Email (`componentType="email"`)
|
|
48
|
+
|
|
49
|
+
- **Format validation**: Automatic email format validation
|
|
50
|
+
- **Autocomplete**: Enhanced with email-specific autocomplete
|
|
51
|
+
|
|
52
|
+
#### Search (`componentType="search"`)
|
|
53
|
+
|
|
54
|
+
- **Clear button**: Native clear functionality on supported browsers
|
|
55
|
+
- **Search behavior**: Platform-specific search enhancements
|
|
16
56
|
|
|
17
57
|
## Inputs
|
|
18
58
|
|
|
59
|
+
### Core Configuration
|
|
60
|
+
|
|
19
61
|
- `componentType`: `'text' | 'textarea' | 'password' | 'email' | 'number' | 'url' | 'search' | 'tel' | 'color'` — Specifies the type of input. **(Required)**
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
62
|
+
|
|
63
|
+
### Text-Specific Inputs
|
|
64
|
+
|
|
65
|
+
- `maxLengthText`: `number | null` — Maximum length for text input. Applies to: `text`, `textarea`, `email`, `password`, `url`, `search`, `tel`
|
|
66
|
+
- `minLengthText`: `number | null` — Minimum length for text input. Applies to: `text`, `textarea`, `email`, `password`, `url`, `search`, `tel`
|
|
67
|
+
|
|
68
|
+
### Number-Specific Inputs
|
|
69
|
+
|
|
70
|
+
- `minNumber`: `number | undefined` — Minimum value for number input. **Only applies to**: `number`
|
|
71
|
+
- `maxNumber`: `number | undefined` — Maximum value for number input. **Only applies to**: `number`
|
|
72
|
+
- `componentStep`: `number` — Step increment for number input. Default: `1`. **Only applies to**: `number`
|
|
73
|
+
|
|
74
|
+
### Textarea-Specific Inputs
|
|
75
|
+
|
|
76
|
+
- `resizable`: `boolean` — Controls textarea resizing behavior. Default: `true`
|
|
77
|
+
|
|
78
|
+
### Password-Specific Inputs
|
|
79
|
+
|
|
80
|
+
- `showHidePasswordButton`: `boolean` — Shows/hides the password toggle button. Default: `true`. **Only applies to**: `password`
|
|
81
|
+
- `buttonClass`: `string` — Additional CSS classes for the password toggle button. **Only applies to**: `password`
|
|
82
|
+
|
|
83
|
+
### Universal Inputs
|
|
84
|
+
|
|
85
|
+
- `isReadonly`: `boolean` — Makes the input read-only
|
|
86
|
+
- `componentLabel`: `string` — Label text (supports i18n keys)
|
|
87
|
+
- `componentPlaceholder`: `string` — Placeholder text (supports i18n keys)
|
|
88
|
+
- `componentTabIndex`: `number` — Tab index for accessibility
|
|
89
|
+
- `componentClass`: `string` — Additional CSS classes for the input element
|
|
90
|
+
- `errorMap`: `Record<string, any>` — Validation error messages
|
|
91
|
+
- `successMessage`: `string` — Success message text
|
|
92
|
+
- `helpMessage`: `string` — Help text displayed below the input
|
|
93
|
+
- `formControl`: `FormControl` — Angular reactive form control
|
|
28
94
|
|
|
29
95
|
## Outputs
|
|
30
96
|
|
|
31
|
-
-
|
|
32
|
-
|
|
97
|
+
- `showPassword`: `EventEmitter<boolean>` — Emitted when the password visibility is toggled (password inputs only)
|
|
98
|
+
- `componentBlur`: `EventEmitter<void>` — Emitted when input loses focus
|
|
33
99
|
|
|
34
100
|
## Usage
|
|
35
101
|
|
|
102
|
+
### Basic Text Input
|
|
103
|
+
|
|
36
104
|
```html
|
|
37
105
|
<quang-input
|
|
38
106
|
[errorMap]="errors()"
|
|
@@ -40,19 +108,75 @@ The `QuangInputComponent` must be configured using the `componentType` input pro
|
|
|
40
108
|
componentType="text"
|
|
41
109
|
formControlName="testInput"
|
|
42
110
|
/>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Password Input with Toggle
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<quang-input
|
|
117
|
+
[errorMap]="errors()"
|
|
118
|
+
[showHidePasswordButton]="true"
|
|
119
|
+
(showPassword)="onToggleShowPassword($event)"
|
|
120
|
+
componentLabel="form.label.password"
|
|
121
|
+
componentType="password"
|
|
122
|
+
formControlName="password"
|
|
123
|
+
>
|
|
124
|
+
@if (showPassword()) {
|
|
125
|
+
<svg-icon src="assets/icons/svg/visibility_off.svg" />
|
|
126
|
+
} @else {
|
|
127
|
+
<svg-icon src="assets/icons/svg/visibility.svg" />
|
|
128
|
+
}
|
|
129
|
+
</quang-input>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### TypeScript Example
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
export class MyComponent {
|
|
136
|
+
showPassword = signal<boolean>(false)
|
|
137
|
+
|
|
138
|
+
onToggleShowPassword(isVisible: boolean): void {
|
|
139
|
+
this.showPassword.set(isVisible)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
errors(): Record<string, any> {
|
|
143
|
+
return this.form.get('password')?.errors ?? {}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Number Input with Constraints
|
|
43
149
|
|
|
150
|
+
```html
|
|
44
151
|
<quang-input
|
|
152
|
+
[componentStep]="5"
|
|
45
153
|
[errorMap]="errors()"
|
|
46
|
-
[
|
|
47
|
-
[maxNumber]="10"
|
|
154
|
+
[maxNumber]="100"
|
|
48
155
|
[minNumber]="0"
|
|
49
|
-
componentLabel="form.label.
|
|
156
|
+
componentLabel="form.label.quantity"
|
|
50
157
|
componentType="number"
|
|
51
|
-
formControlName="
|
|
52
|
-
successMessage="form.label.success"
|
|
158
|
+
formControlName="quantity"
|
|
53
159
|
/>
|
|
54
160
|
```
|
|
55
161
|
|
|
56
|
-
|
|
162
|
+
### Textarea
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<quang-input
|
|
166
|
+
[errorMap]="errors()"
|
|
167
|
+
[maxLengthText]="500"
|
|
168
|
+
componentLabel="form.label.description"
|
|
169
|
+
componentType="textarea"
|
|
170
|
+
formControlName="description"
|
|
171
|
+
/>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Type-Specific Features
|
|
175
|
+
|
|
176
|
+
The component supports various input types with specific behaviors:
|
|
57
177
|
|
|
58
|
-
|
|
178
|
+
- **text, email, url, search, tel**: Support text length constraints
|
|
179
|
+
- **password**: Built-in show/hide toggle functionality with icon support
|
|
180
|
+
- **number**: Step controls and min/max validation
|
|
181
|
+
- **textarea**: Multi-line support with resizable control
|
|
182
|
+
- **color**: Color picker input
|
|
@@ -10,9 +10,15 @@ declare class QuangInputComponent extends QuangBaseComponent<string | number> {
|
|
|
10
10
|
maxNumber: _angular_core.InputSignal<number | undefined>;
|
|
11
11
|
componentStep: _angular_core.InputSignal<number>;
|
|
12
12
|
resizable: _angular_core.InputSignal<boolean>;
|
|
13
|
+
buttonClass: _angular_core.InputSignal<string>;
|
|
14
|
+
showHidePasswordButton: _angular_core.InputSignal<boolean>;
|
|
15
|
+
showPassword: _angular_core.OutputEmitterRef<boolean>;
|
|
16
|
+
private onShowPassword;
|
|
17
|
+
componentInputType: _angular_core.Signal<InputType>;
|
|
13
18
|
constructor();
|
|
19
|
+
onTogglePasswordVisibility(): void;
|
|
14
20
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<QuangInputComponent, never>;
|
|
15
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<QuangInputComponent, "quang-input", never, { "componentType": { "alias": "componentType"; "required": true; "isSignal": true; }; "maxLengthText": { "alias": "maxLengthText"; "required": false; "isSignal": true; }; "minLengthText": { "alias": "minLengthText"; "required": false; "isSignal": true; }; "minNumber": { "alias": "minNumber"; "required": false; "isSignal": true; }; "maxNumber": { "alias": "maxNumber"; "required": false; "isSignal": true; }; "componentStep": { "alias": "componentStep"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; }, {}, never,
|
|
21
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<QuangInputComponent, "quang-input", never, { "componentType": { "alias": "componentType"; "required": true; "isSignal": true; }; "maxLengthText": { "alias": "maxLengthText"; "required": false; "isSignal": true; }; "minLengthText": { "alias": "minLengthText"; "required": false; "isSignal": true; }; "minNumber": { "alias": "minNumber"; "required": false; "isSignal": true; }; "maxNumber": { "alias": "maxNumber"; "required": false; "isSignal": true; }; "componentStep": { "alias": "componentStep"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; "buttonClass": { "alias": "buttonClass"; "required": false; "isSignal": true; }; "showHidePasswordButton": { "alias": "showHidePasswordButton"; "required": false; "isSignal": true; }; }, { "showPassword": "showPassword"; }, never, ["*"], true, never>;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
export { QuangInputComponent };
|
|
@@ -1,43 +1,67 @@
|
|
|
1
1
|
# QuangPaginatorComponent
|
|
2
2
|
|
|
3
|
-
The `QuangPaginatorComponent`
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Pagination controls
|
|
8
|
-
- Configurable total items, items per page, and current page
|
|
9
|
-
- Emits events for page changes
|
|
3
|
+
The `QuangPaginatorComponent` is a pagination control that provides navigation through large datasets with configurable page sizes and internationalization support.
|
|
10
4
|
|
|
11
5
|
## Inputs
|
|
12
6
|
|
|
13
|
-
- `page`: `number` — Current page number. **(Required)**
|
|
14
|
-
- `pageSize`: `number` — Number of items per page. **(Required)**
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `showTotalElementsCount`: `boolean` —
|
|
18
|
-
- `totalItemsText`: `string` — Translation key for total items label. Default: `'quangPaginator.totalItems'
|
|
19
|
-
- `sizeText`: `string` — Translation key for size label. Default: `'quangPaginator.size'
|
|
20
|
-
- `pageRangeText`: `string` — Translation key for page range
|
|
21
|
-
- `componentId
|
|
7
|
+
- `page`: `number` — Current active page number (1-based indexing). **(Required)**
|
|
8
|
+
- `pageSize`: `number` — Number of items displayed per page. **(Required)**
|
|
9
|
+
- `totalItems`: `number` — Total number of items in the dataset. **(Required)**
|
|
10
|
+
- `sizeList`: `number[]` — Array of available page size options for user selection. Default: `[]`
|
|
11
|
+
- `showTotalElementsCount`: `boolean` — Controls visibility of total items count display. Default: `true`
|
|
12
|
+
- `totalItemsText`: `string` — Translation key for total items label text. Default: `'quangPaginator.totalItems'`
|
|
13
|
+
- `sizeText`: `string` — Translation key for page size selector label. Default: `'quangPaginator.size'`
|
|
14
|
+
- `pageRangeText`: `string` — Translation key for page range display. Must include `{{page}}` and `{{amountPages}}` placeholders. Default: `'quangPaginator.pageRange'`
|
|
15
|
+
- `componentId`: `string` — Unique identifier for the paginator instance
|
|
16
|
+
- `componentTabIndex`: `number` — Base tab index for paginator controls. Default: `0`
|
|
17
|
+
- `componentClass`: `string | string[]` — Additional CSS classes for styling customization
|
|
22
18
|
|
|
23
19
|
## Outputs
|
|
24
20
|
|
|
25
|
-
- `changePage`:
|
|
26
|
-
- `changeSize`:
|
|
21
|
+
- `changePage`: `EventEmitter<number>` — Emitted when user navigates to a different page
|
|
22
|
+
- `changeSize`: `EventEmitter<number>` — Emitted when user changes the page size
|
|
27
23
|
|
|
28
24
|
## Usage
|
|
29
25
|
|
|
26
|
+
### Basic Paginator
|
|
27
|
+
|
|
30
28
|
```html
|
|
31
29
|
<quang-paginator
|
|
32
|
-
[page]="
|
|
33
|
-
[pageSize]="
|
|
34
|
-
[
|
|
35
|
-
|
|
36
|
-
(
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
[page]="currentPage"
|
|
31
|
+
[pageSize]="itemsPerPage"
|
|
32
|
+
[totalItems]="totalItemCount"
|
|
33
|
+
(changePage)="onPageChange($event)"
|
|
34
|
+
(changeSize)="onPageSizeChange($event)"
|
|
35
|
+
>
|
|
36
|
+
</quang-paginator>
|
|
39
37
|
```
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
#### TypeScript Example
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
export class MyComponent {
|
|
43
|
+
currentPage = 1
|
|
44
|
+
itemsPerPage = 20
|
|
45
|
+
totalItemCount = 150
|
|
46
|
+
|
|
47
|
+
onPageChange(page: number): void {
|
|
48
|
+
this.currentPage = page
|
|
49
|
+
// Load data for new page
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onPageSizeChange(pageSize: number): void {
|
|
53
|
+
this.itemsPerPage = pageSize
|
|
54
|
+
this.currentPage = 1 // Reset to first page
|
|
55
|
+
// Load data with new page size
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Translation Integration
|
|
61
|
+
|
|
62
|
+
The component uses QuangTranslationService for all text content:
|
|
42
63
|
|
|
43
|
-
|
|
64
|
+
- **Default Keys**: Uses `quangPaginator.*` translation keys
|
|
65
|
+
- **Custom Override**: All text keys can be overridden via inputs
|
|
66
|
+
- **Placeholder Support**: Page range text supports `{{page}}` and `{{amountPages}}` placeholders
|
|
67
|
+
- **Dynamic Translation**: Responds to language changes automatically
|
|
@@ -2,53 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
The `QuangSelectComponent` supports single or multiple selections from a dropdown list.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Input
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- Customizable options
|
|
7
|
+
- `selectOptions`: `SelectOption[]` - Array of options to display in the dropdown (required)
|
|
8
|
+
- `selectionMode`: `'single' | 'multiple'` - Selection mode (default: 'single')
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
All standard inputs inherited from `QuangBaseComponent`: `isReadonly`, `componentLabel`, `componentPlaceholder`, `componentTabIndex`, `componentClass`, `errorMap`, `successMessage`, `helpMessage`, `formControl`
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
- `selectionMode`: `'single' | 'multiple'` — Enables single or multiple selection mode. Default: `'single'`.
|
|
15
|
-
- All standard form/label/validation-related inputs inherited from `QuangBaseComponent`:
|
|
16
|
-
- `isReadonly`, `componentLabel`, `componentPlaceholder`, `componentTabIndex`, `componentClass`, `errorMap`, `successMessage`, `helpMessage`, `formControl`
|
|
12
|
+
## Output
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- All standard outputs inherited from `QuangBaseComponent`:
|
|
21
|
-
- `componentBlur`
|
|
14
|
+
All standard outputs inherited from `QuangBaseComponent`: `componentBlur`
|
|
22
15
|
|
|
23
16
|
## Usage
|
|
24
17
|
|
|
18
|
+
### Single Selection
|
|
25
19
|
```html
|
|
26
20
|
<quang-select
|
|
27
21
|
[errorMap]="errors()"
|
|
28
|
-
[isReadonly]="isReadonly()"
|
|
29
22
|
[selectOptions]="stringList"
|
|
30
|
-
class="col-4"
|
|
31
23
|
componentLabel="form.label.select"
|
|
32
|
-
componentPlaceholder="
|
|
24
|
+
componentPlaceholder="Select an option"
|
|
33
25
|
formControlName="testInput"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/>
|
|
26
|
+
selectionMode="single">
|
|
27
|
+
</quang-select>
|
|
28
|
+
```
|
|
38
29
|
|
|
30
|
+
### Multiple Selection
|
|
31
|
+
```html
|
|
39
32
|
<quang-select
|
|
40
33
|
[errorMap]="errors()"
|
|
41
|
-
[isReadonly]="isReadonly()"
|
|
42
34
|
[selectOptions]="numberList"
|
|
43
|
-
class="col-4"
|
|
44
35
|
componentLabel="form.label.multipleSelect"
|
|
45
|
-
componentPlaceholder="
|
|
36
|
+
componentPlaceholder="Select multiple options"
|
|
46
37
|
formControlName="testInputMultiple"
|
|
47
|
-
selectionMode="multiple"
|
|
48
|
-
|
|
49
|
-
/>
|
|
38
|
+
selectionMode="multiple">
|
|
39
|
+
</quang-select>
|
|
50
40
|
```
|
|
51
41
|
|
|
52
|
-
##
|
|
42
|
+
## QuangTranslationService Integration
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
The component supports automatic translation of all labels, help messages, and error messages through `QuangTranslationService`.
|
|
@@ -1,24 +1,90 @@
|
|
|
1
1
|
# QuangTableComponent
|
|
2
2
|
|
|
3
|
-
The `QuangTableComponent` allows for displaying data in a tabular format.
|
|
3
|
+
The `QuangTableComponent` allows for displaying data in a tabular format with advanced features for customization, sorting, and row selection.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- Tabular data display
|
|
8
8
|
- Customizable headers and rows
|
|
9
|
-
- Supports sorting
|
|
9
|
+
- Supports sorting by columns
|
|
10
|
+
- Custom cell rendering with templates
|
|
11
|
+
- Row selection and highlighting
|
|
12
|
+
- Sticky header option
|
|
13
|
+
|
|
14
|
+
## Interfaces
|
|
15
|
+
|
|
16
|
+
### TableConfiguration<T>
|
|
17
|
+
```typescript
|
|
18
|
+
interface TableConfiguration<T> {
|
|
19
|
+
headers: TableHeader[];
|
|
20
|
+
rows: TableRow<T>[];
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### TableHeader
|
|
25
|
+
```typescript
|
|
26
|
+
interface TableHeader {
|
|
27
|
+
text?: string; // Display text for the header
|
|
28
|
+
sort?: SortCol; // Sort configuration for the column
|
|
29
|
+
css?: string[]; // CSS classes to apply to the header
|
|
30
|
+
renderer?: TemplateRef<any>; // Custom template for header rendering
|
|
31
|
+
payload?: any; // Additional data that can be used in custom renderers
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### TableRow<T>
|
|
36
|
+
```typescript
|
|
37
|
+
interface TableRow<T> {
|
|
38
|
+
payload?: T; // The data object for this row
|
|
39
|
+
rowId?: string | number; // Unique identifier for the row
|
|
40
|
+
css?: string[]; // CSS classes to apply to the row
|
|
41
|
+
cellData: TableCell[]; // Array of cells in this row
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### TableCell
|
|
46
|
+
```typescript
|
|
47
|
+
interface TableCell {
|
|
48
|
+
renderer?: TemplateRef<any>; // Custom template for cell rendering
|
|
49
|
+
payload?: any; // Additional data that can be used in custom renderers
|
|
50
|
+
text?: string; // Display text for the cell
|
|
51
|
+
css?: string[]; // CSS classes to apply to the cell
|
|
52
|
+
fullWidth?: boolean; // Whether the cell should span the full width
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### SortCol
|
|
57
|
+
```typescript
|
|
58
|
+
interface SortCol {
|
|
59
|
+
key: string; // Identifier for the column
|
|
60
|
+
sort: SortTable; // Sort direction (DEFAULT, ASC, DESC)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
10
63
|
|
|
11
64
|
## Inputs
|
|
12
65
|
|
|
13
|
-
- `tableConfigurations`: `
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
66
|
+
- `tableConfigurations`: `TableConfiguration<T>` — Table configuration object containing headers and rows. **(Required)**
|
|
67
|
+
- This object defines the structure and data of your table.
|
|
68
|
+
|
|
69
|
+
- `clickableRow`: `boolean` — Whether rows should be clickable. Default: `false`.
|
|
70
|
+
- When true, clicking a row will emit the row data through the `selectedRow` output.
|
|
71
|
+
|
|
72
|
+
- `selectedRows`: `string[] | number[]` — Array of rowIds that should be marked as selected.
|
|
73
|
+
- Use this to highlight specific rows in the table.
|
|
74
|
+
|
|
75
|
+
- `stickyTable`: `boolean` — Enables sticky header. Default: `true`.
|
|
76
|
+
- When true, the header will remain visible when scrolling.
|
|
77
|
+
|
|
78
|
+
- `noResultsText`: `string` — Text to display when no data is available. Default: 'quangTable.noResults'.
|
|
79
|
+
- This supports translation keys if using transloco.
|
|
17
80
|
|
|
18
81
|
## Outputs
|
|
19
82
|
|
|
20
|
-
- `sortChanged`:
|
|
21
|
-
-
|
|
83
|
+
- `sortChanged`: `EventEmitter<SortCol[]>` — Emits when the user changes the sorting of a column.
|
|
84
|
+
- Returns an array of SortCol objects with the updated sorting state.
|
|
85
|
+
|
|
86
|
+
- `selectedRow`: `EventEmitter<TableRow<T>>` — Emits when a row is clicked (if clickableRow is true).
|
|
87
|
+
- Returns the full row data including payload.
|
|
22
88
|
|
|
23
89
|
## Usage
|
|
24
90
|
|
|
@@ -26,38 +92,148 @@ The `QuangTableComponent` allows for displaying data in a tabular format.
|
|
|
26
92
|
|
|
27
93
|
```html
|
|
28
94
|
<quang-table
|
|
29
|
-
[stickyTable]="true"
|
|
30
95
|
[tableConfigurations]="tableConfig()"
|
|
96
|
+
[clickableRow]="true"
|
|
97
|
+
[stickyTable]="true"
|
|
98
|
+
[selectedRows]="selectedRowIds()"
|
|
99
|
+
(selectedRow)="onRowClick($event)"
|
|
31
100
|
(sortChanged)="onChangeSort($event)"
|
|
32
|
-
(rowClick)="onRowClick($event)"
|
|
33
101
|
/>
|
|
34
102
|
```
|
|
35
103
|
|
|
36
104
|
### TypeScript
|
|
37
105
|
|
|
38
106
|
```typescript
|
|
39
|
-
import {
|
|
107
|
+
import { Component, signal, computed } from '@angular/core';
|
|
108
|
+
import {
|
|
109
|
+
TableConfiguration,
|
|
110
|
+
TableHeader,
|
|
111
|
+
TableRow,
|
|
112
|
+
TableCell,
|
|
113
|
+
SortTable,
|
|
114
|
+
SortCol
|
|
115
|
+
} from 'quang/components/table';
|
|
116
|
+
|
|
117
|
+
@Component({
|
|
118
|
+
selector: 'app-example',
|
|
119
|
+
templateUrl: './example.component.html',
|
|
120
|
+
})
|
|
121
|
+
export class ExampleComponent {
|
|
122
|
+
// Sample data
|
|
123
|
+
userData = signal([
|
|
124
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', age: 30 },
|
|
125
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 25 },
|
|
126
|
+
{ id: 3, name: 'Alice Johnson', email: 'alice@example.com', age: 35 },
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
selectedRowIds = signal<number[]>([1]); // Row with ID 1 will be highlighted
|
|
130
|
+
|
|
131
|
+
// Define headers
|
|
132
|
+
tableHeaders = [
|
|
133
|
+
{
|
|
134
|
+
text: 'ID',
|
|
135
|
+
sort: { key: 'id', sort: SortTable.DEFAULT }
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
text: 'Name',
|
|
139
|
+
sort: { key: 'name', sort: SortTable.DEFAULT }
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
text: 'Email',
|
|
143
|
+
sort: { key: 'email', sort: SortTable.DEFAULT }
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
text: 'Age',
|
|
147
|
+
sort: { key: 'age', sort: SortTable.DEFAULT }
|
|
148
|
+
}
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
// Compute rows from data
|
|
152
|
+
tableRows = computed(() =>
|
|
153
|
+
this.userData().map(user => ({
|
|
154
|
+
rowId: user.id,
|
|
155
|
+
payload: user,
|
|
156
|
+
cellData: [
|
|
157
|
+
{ text: user.id.toString() },
|
|
158
|
+
{ text: user.name },
|
|
159
|
+
{ text: user.email },
|
|
160
|
+
{ text: user.age.toString() }
|
|
161
|
+
]
|
|
162
|
+
}))
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// Combine headers and rows into table configuration
|
|
166
|
+
tableConfig = computed<TableConfiguration<any>>(() => ({
|
|
167
|
+
headers: this.tableHeaders,
|
|
168
|
+
rows: this.tableRows()
|
|
169
|
+
}));
|
|
170
|
+
|
|
171
|
+
onRowClick(row: TableRow<any>): void {
|
|
172
|
+
console.log('Row clicked:', row.payload);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
onChangeSort(sortCols: SortCol[]): void {
|
|
176
|
+
const sortCol = sortCols[0];
|
|
177
|
+
const sortDirection = sortCol.sort;
|
|
178
|
+
|
|
179
|
+
// Sort data based on column and direction
|
|
180
|
+
this.userData.update(users => {
|
|
181
|
+
return [...users].sort((a, b) => {
|
|
182
|
+
if (sortDirection === SortTable.DEFAULT) {
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const modifier = sortDirection === SortTable.ASC ? 1 : -1;
|
|
187
|
+
const aValue = a[sortCol.key];
|
|
188
|
+
const bValue = b[sortCol.key];
|
|
189
|
+
|
|
190
|
+
if (aValue < bValue) return -1 * modifier;
|
|
191
|
+
if (aValue > bValue) return 1 * modifier;
|
|
192
|
+
return 0;
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Advanced Usage with Custom Templates
|
|
40
200
|
|
|
41
|
-
|
|
201
|
+
You can use templates to customize cell rendering:
|
|
42
202
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
])
|
|
203
|
+
```html
|
|
204
|
+
<ng-template #nameTemplate let-data>
|
|
205
|
+
<strong>{{ data.name }}</strong>
|
|
206
|
+
</ng-template>
|
|
48
207
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{ key: 'age', label: 'Age', sortable: false },
|
|
53
|
-
]
|
|
208
|
+
<quang-table [tableConfigurations]="customTableConfig()">
|
|
209
|
+
</quang-table>
|
|
210
|
+
```
|
|
54
211
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
212
|
+
```typescript
|
|
213
|
+
nameTemplate = TemplateRef<ane>('nameTemplate')
|
|
214
|
+
|
|
215
|
+
customTableConfig = computed(() => ({
|
|
216
|
+
headers: [
|
|
217
|
+
{ text: 'ID' },
|
|
218
|
+
{ text: 'Name', renderer: this.nameTemplate },
|
|
219
|
+
{ text: 'Email' },
|
|
220
|
+
{ text: 'Age' }
|
|
221
|
+
],
|
|
222
|
+
rows: this.userData().map(user => ({
|
|
223
|
+
rowId: user.id,
|
|
224
|
+
payload: user,
|
|
225
|
+
cellData: [
|
|
226
|
+
{ text: user.id.toString() },
|
|
227
|
+
{ payload: user }, // This will be accessible in the template
|
|
228
|
+
{ text: user.email },
|
|
229
|
+
{ text: user.age.toString() }
|
|
230
|
+
]
|
|
231
|
+
}))
|
|
58
232
|
}))
|
|
59
233
|
```
|
|
60
234
|
|
|
61
235
|
## Notes
|
|
62
236
|
|
|
63
|
-
|
|
237
|
+
- The table automatically adjusts column widths to match content.
|
|
238
|
+
- Use CSS classes to customize the appearance of specific rows, headers, or cells.
|
|
239
|
+
- For responsive tables, consider setting appropriate container widths.
|