@memberjunction/ng-record-selector 2.42.1 → 2.44.0
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 +181 -54
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @memberjunction/ng-record-selector
|
|
2
2
|
|
|
3
|
-
An Angular component for selecting records from
|
|
3
|
+
An Angular component library for selecting records from dual lists in MemberJunction applications. This package provides both a standalone selection component and a dialog wrapper component for easy integration.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@memberjunction/ng-record-selector` package provides Angular components that allow users to select and deselect items from a possible set using a dual listbox interface. It's designed to work seamlessly with MemberJunction's BaseEntity objects and provides a clean, intuitive UI for managing selections.
|
|
4
8
|
|
|
5
9
|
## Features
|
|
6
10
|
|
|
7
|
-
- **Dual Listbox Interface**:
|
|
8
|
-
- **Drag and Drop**: Intuitive item movement between lists
|
|
9
|
-
- **Double-Click Support**: Quickly move items by double-clicking
|
|
10
|
-
- **Icon Support**: Display icons alongside item text
|
|
11
|
-
- **Configurable Toolbar**: Customize available toolbar actions
|
|
12
|
-
- **Dialog Integration**: Optional dialog wrapper for modal usage
|
|
13
|
-
- **Entity Integration**: Works with MemberJunction BaseEntity objects
|
|
14
|
-
- **
|
|
11
|
+
- **Dual Listbox Interface**: Side-by-side lists for available and selected items
|
|
12
|
+
- **Drag and Drop**: Intuitive item movement between lists using Kendo UI's drag and drop functionality
|
|
13
|
+
- **Double-Click Support**: Quickly move items between lists by double-clicking
|
|
14
|
+
- **Icon Support**: Display icons alongside item text using CSS classes from entity fields
|
|
15
|
+
- **Configurable Toolbar**: Customize available toolbar actions (move up/down, transfer items, transfer all)
|
|
16
|
+
- **Dialog Integration**: Optional dialog wrapper for modal usage with OK/Cancel functionality
|
|
17
|
+
- **Entity Integration**: Works natively with MemberJunction BaseEntity objects
|
|
18
|
+
- **State Management**: Dialog component maintains selection state and can revert changes on cancel
|
|
19
|
+
- **Responsive Design**: Uses MemberJunction's container directives for proper layout
|
|
15
20
|
|
|
16
21
|
## Installation
|
|
17
22
|
|
|
@@ -19,6 +24,8 @@ An Angular component for selecting records from a list of available items in Mem
|
|
|
19
24
|
npm install @memberjunction/ng-record-selector
|
|
20
25
|
```
|
|
21
26
|
|
|
27
|
+
Note: This package has peer dependencies on Angular 18.0.2 and Kendo UI Angular components. Ensure these are installed in your project.
|
|
28
|
+
|
|
22
29
|
## Usage
|
|
23
30
|
|
|
24
31
|
### Import the Module
|
|
@@ -42,8 +49,8 @@ export class YourModule { }
|
|
|
42
49
|
<!-- Standalone selector component -->
|
|
43
50
|
<mj-record-selector
|
|
44
51
|
[EntityName]="'Users'"
|
|
45
|
-
[DisplayField]="'
|
|
46
|
-
[DisplayIconField]="'
|
|
52
|
+
[DisplayField]="'Name'"
|
|
53
|
+
[DisplayIconField]="'IconCSSClass'"
|
|
47
54
|
[AvailableRecords]="allUsers"
|
|
48
55
|
[SelectedRecords]="selectedUsers"
|
|
49
56
|
[UnselectedRecords]="unselectedUsers"
|
|
@@ -52,6 +59,8 @@ export class YourModule { }
|
|
|
52
59
|
</mj-record-selector>
|
|
53
60
|
```
|
|
54
61
|
|
|
62
|
+
**Note**: The component accesses entity field values directly using bracket notation (e.g., `dataItem[DisplayField]`), so ensure your DisplayField and DisplayIconField names match the actual property names in your BaseEntity objects.
|
|
63
|
+
|
|
55
64
|
### Dialog Component Usage
|
|
56
65
|
|
|
57
66
|
```html
|
|
@@ -63,7 +72,8 @@ export class YourModule { }
|
|
|
63
72
|
<mj-record-selector-dialog
|
|
64
73
|
*ngIf="showSelectorDialog"
|
|
65
74
|
[EntityName]="'Users'"
|
|
66
|
-
[DisplayField]="'
|
|
75
|
+
[DisplayField]="'Name'"
|
|
76
|
+
[DisplayIconField]="'IconCSSClass'"
|
|
67
77
|
[AvailableRecords]="allUsers"
|
|
68
78
|
[SelectedRecords]="selectedUsers"
|
|
69
79
|
[UnselectedRecords]="unselectedUsers"
|
|
@@ -80,6 +90,7 @@ export class YourModule { }
|
|
|
80
90
|
```typescript
|
|
81
91
|
import { Component, OnInit } from '@angular/core';
|
|
82
92
|
import { BaseEntity, Metadata, RunView } from '@memberjunction/core';
|
|
93
|
+
import { UserEntity } from '@memberjunction/core-entities';
|
|
83
94
|
import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
|
|
84
95
|
|
|
85
96
|
@Component({
|
|
@@ -92,7 +103,7 @@ import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
|
|
|
92
103
|
<h4>Selected Users ({{ selectedUsers.length }}):</h4>
|
|
93
104
|
<ul>
|
|
94
105
|
<li *ngFor="let user of selectedUsers">
|
|
95
|
-
{{ user.
|
|
106
|
+
{{ user.Name }} - {{ user.Email }}
|
|
96
107
|
</li>
|
|
97
108
|
</ul>
|
|
98
109
|
<button kendoButton (click)="saveUserAssignments()">Save Assignments</button>
|
|
@@ -101,8 +112,8 @@ import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
|
|
|
101
112
|
<mj-record-selector-dialog
|
|
102
113
|
*ngIf="selectorDialogVisible"
|
|
103
114
|
[EntityName]="'Users'"
|
|
104
|
-
[DisplayField]="'
|
|
105
|
-
[DisplayIconField]="'
|
|
115
|
+
[DisplayField]="'Name'"
|
|
116
|
+
[DisplayIconField]="'IconCSSClass'"
|
|
106
117
|
[AvailableRecords]="allUsers"
|
|
107
118
|
[SelectedRecords]="selectedUsers"
|
|
108
119
|
[UnselectedRecords]="unselectedUsers"
|
|
@@ -116,9 +127,9 @@ import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
|
|
|
116
127
|
`
|
|
117
128
|
})
|
|
118
129
|
export class UserRoleAssignmentComponent implements OnInit {
|
|
119
|
-
allUsers:
|
|
120
|
-
selectedUsers:
|
|
121
|
-
unselectedUsers:
|
|
130
|
+
allUsers: UserEntity[] = [];
|
|
131
|
+
selectedUsers: UserEntity[] = [];
|
|
132
|
+
unselectedUsers: UserEntity[] = [];
|
|
122
133
|
selectorDialogVisible = false;
|
|
123
134
|
|
|
124
135
|
toolbarSettings: ListBoxToolbarConfig = {
|
|
@@ -133,9 +144,9 @@ export class UserRoleAssignmentComponent implements OnInit {
|
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
async loadUsers() {
|
|
136
|
-
// Load all users
|
|
147
|
+
// Load all users using MemberJunction's recommended pattern
|
|
137
148
|
const rv = new RunView();
|
|
138
|
-
const result = await rv.RunView({
|
|
149
|
+
const result = await rv.RunView<UserEntity>({
|
|
139
150
|
EntityName: 'Users',
|
|
140
151
|
ResultType: 'entity_object'
|
|
141
152
|
});
|
|
@@ -159,14 +170,19 @@ export class UserRoleAssignmentComponent implements OnInit {
|
|
|
159
170
|
|
|
160
171
|
if (confirmed) {
|
|
161
172
|
console.log('User selection confirmed:', this.selectedUsers);
|
|
173
|
+
// The selectedUsers array has been updated by the dialog component
|
|
162
174
|
} else {
|
|
163
175
|
console.log('User selection cancelled');
|
|
176
|
+
// The dialog component has already reverted any changes
|
|
164
177
|
}
|
|
165
178
|
}
|
|
166
179
|
|
|
167
|
-
saveUserAssignments() {
|
|
168
|
-
//
|
|
169
|
-
|
|
180
|
+
async saveUserAssignments() {
|
|
181
|
+
// Example: Save user role assignments
|
|
182
|
+
for (const user of this.selectedUsers) {
|
|
183
|
+
// Create role assignment records or update user roles
|
|
184
|
+
console.log(`Assigning role to user: ${user.Name} (${user.ID})`);
|
|
185
|
+
}
|
|
170
186
|
}
|
|
171
187
|
}
|
|
172
188
|
```
|
|
@@ -175,39 +191,72 @@ export class UserRoleAssignmentComponent implements OnInit {
|
|
|
175
191
|
|
|
176
192
|
### RecordSelectorComponent
|
|
177
193
|
|
|
178
|
-
|
|
194
|
+
The base component that provides the dual listbox functionality for selecting records.
|
|
195
|
+
|
|
196
|
+
**Selector**: `mj-record-selector`
|
|
179
197
|
|
|
180
198
|
#### Inputs
|
|
181
199
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
200
|
+
| Input | Type | Default | Description |
|
|
201
|
+
|-------|------|---------|-------------|
|
|
202
|
+
| `EntityName` | `string` | `''` | The name of the entity to show records for |
|
|
203
|
+
| `DisplayField` | `string` | `''` | The field name to display in the list items |
|
|
204
|
+
| `DisplayIconField` | `string` | `''` | The field name containing CSS class for icons (optional) |
|
|
205
|
+
| `AvailableRecords` | `BaseEntity[]` | `[]` | List of all available records |
|
|
206
|
+
| `SelectedRecords` | `BaseEntity[]` | `[]` | List of currently selected records |
|
|
207
|
+
| `UnselectedRecords` | `BaseEntity[]` | `[]` | List of currently unselected records |
|
|
208
|
+
| `ToolbarSettings` | `ListBoxToolbarConfig` | See below | Configuration for the listbox toolbar |
|
|
209
|
+
|
|
210
|
+
Default toolbar settings:
|
|
211
|
+
```typescript
|
|
212
|
+
{
|
|
213
|
+
position: "right",
|
|
214
|
+
tools: ["moveUp", "transferFrom", "transferAllFrom", "transferAllTo", "transferTo", "moveDown"]
|
|
215
|
+
}
|
|
216
|
+
```
|
|
189
217
|
|
|
190
218
|
#### Outputs
|
|
191
219
|
|
|
192
|
-
|
|
193
|
-
|
|
220
|
+
| Output | Type | Description |
|
|
221
|
+
|--------|------|-------------|
|
|
222
|
+
| `RecordSelected` | `EventEmitter<BaseEntity[]>` | Emitted when records are moved to the selected list |
|
|
223
|
+
| `RecordUnselected` | `EventEmitter<BaseEntity[]>` | Emitted when records are moved to the unselected list |
|
|
224
|
+
|
|
225
|
+
#### Methods
|
|
226
|
+
|
|
227
|
+
The component handles double-click events internally to move items between lists. No public methods are exposed.
|
|
194
228
|
|
|
195
229
|
### RecordSelectorDialogComponent
|
|
196
230
|
|
|
197
|
-
|
|
231
|
+
A dialog wrapper that contains the RecordSelectorComponent with OK/Cancel functionality.
|
|
232
|
+
|
|
233
|
+
**Selector**: `mj-record-selector-dialog`
|
|
198
234
|
|
|
199
235
|
#### Inputs
|
|
200
236
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
237
|
+
Inherits all inputs from `RecordSelectorComponent`, plus:
|
|
238
|
+
|
|
239
|
+
| Input | Type | Default | Description |
|
|
240
|
+
|-------|------|---------|-------------|
|
|
241
|
+
| `DialogTitle` | `string` | `'Select Records'` | Title displayed in the dialog header |
|
|
242
|
+
| `DialogWidth` | `string` | `'700px'` | Width of the dialog |
|
|
243
|
+
| `DialogHeight` | `string` | `'450px'` | Height of the dialog |
|
|
244
|
+
| `DialogVisible` | `boolean` | `false` | Controls the visibility of the dialog |
|
|
206
245
|
|
|
207
246
|
#### Outputs
|
|
208
247
|
|
|
209
|
-
|
|
210
|
-
|
|
248
|
+
Inherits all outputs from `RecordSelectorComponent`, plus:
|
|
249
|
+
|
|
250
|
+
| Output | Type | Description |
|
|
251
|
+
|--------|------|-------------|
|
|
252
|
+
| `DialogClosed` | `EventEmitter<boolean>` | Emitted when the dialog is closed. `true` if OK was clicked, `false` if Cancel was clicked or dialog was closed by other means |
|
|
253
|
+
|
|
254
|
+
#### Behavior
|
|
255
|
+
|
|
256
|
+
- When the dialog is opened, it saves the initial state of selected/unselected records
|
|
257
|
+
- Clicking OK commits the changes and closes the dialog
|
|
258
|
+
- Clicking Cancel or closing the dialog by other means reverts all changes to the initial state
|
|
259
|
+
- The component maintains references to the same arrays passed in as inputs, modifying them in place
|
|
211
260
|
|
|
212
261
|
## Toolbar Configuration
|
|
213
262
|
|
|
@@ -229,22 +278,100 @@ const toolbarSettings: ListBoxToolbarConfig = {
|
|
|
229
278
|
|
|
230
279
|
## Selection Behavior
|
|
231
280
|
|
|
232
|
-
The component uses Kendo UI ListBox components with the following
|
|
281
|
+
The component uses Kendo UI ListBox components with the following interaction patterns:
|
|
233
282
|
|
|
234
|
-
1.
|
|
235
|
-
2. Items can be dragged
|
|
236
|
-
3. Double-clicking an item moves it to the
|
|
237
|
-
4.
|
|
283
|
+
1. **Toolbar Actions**: Use the toolbar buttons to move items between lists
|
|
284
|
+
2. **Drag and Drop**: Items can be dragged from one list to another
|
|
285
|
+
3. **Double-Click**: Double-clicking an item instantly moves it to the opposite list
|
|
286
|
+
4. **Multi-Select**: Hold Ctrl/Cmd to select multiple items, or Shift to select a range
|
|
287
|
+
5. **Dialog State Management**: When using the dialog wrapper:
|
|
288
|
+
- Changes are held in memory until confirmed
|
|
289
|
+
- OK button commits all changes
|
|
290
|
+
- Cancel button reverts to the initial state
|
|
238
291
|
|
|
239
292
|
## Styling
|
|
240
293
|
|
|
241
|
-
The component uses Kendo UI ListBox
|
|
294
|
+
The component uses Kendo UI ListBox styles with additional custom styling:
|
|
295
|
+
|
|
296
|
+
- `.list-box`: Applied to each listbox container
|
|
297
|
+
- `.item-icon`: Applied to icon spans when DisplayIconField is used
|
|
298
|
+
|
|
299
|
+
You can override these styles in your application's CSS:
|
|
300
|
+
|
|
301
|
+
```css
|
|
302
|
+
/* Example: Custom styling for the record selector */
|
|
303
|
+
mj-record-selector .list-box {
|
|
304
|
+
min-height: 300px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
mj-record-selector .item-icon {
|
|
308
|
+
margin-right: 8px;
|
|
309
|
+
color: #666;
|
|
310
|
+
}
|
|
311
|
+
```
|
|
242
312
|
|
|
243
313
|
## Dependencies
|
|
244
314
|
|
|
245
|
-
|
|
246
|
-
- `@memberjunction/core
|
|
247
|
-
- `@memberjunction/
|
|
248
|
-
- `@
|
|
249
|
-
- `@
|
|
250
|
-
- `@
|
|
315
|
+
### Runtime Dependencies
|
|
316
|
+
- `@memberjunction/core`: ^2.43.0 - Core MemberJunction functionality
|
|
317
|
+
- `@memberjunction/core-entities`: ^2.43.0 - Entity type definitions
|
|
318
|
+
- `@memberjunction/global`: ^2.43.0 - Global utilities and types
|
|
319
|
+
- `@memberjunction/ng-container-directives`: ^2.43.0 - Layout directives
|
|
320
|
+
- `@memberjunction/ng-shared`: ^2.43.0 - Shared Angular utilities
|
|
321
|
+
|
|
322
|
+
### Peer Dependencies
|
|
323
|
+
- `@angular/common`: 18.0.2
|
|
324
|
+
- `@angular/core`: 18.0.2
|
|
325
|
+
- `@angular/forms`: 18.0.2
|
|
326
|
+
- `@angular/router`: 18.0.2
|
|
327
|
+
- `@progress/kendo-angular-buttons`: 16.2.0
|
|
328
|
+
- `@progress/kendo-angular-dialog`: 16.2.0
|
|
329
|
+
- `@progress/kendo-angular-listbox`: 16.2.0
|
|
330
|
+
|
|
331
|
+
## Integration with Other MemberJunction Packages
|
|
332
|
+
|
|
333
|
+
This package integrates seamlessly with other MemberJunction components:
|
|
334
|
+
|
|
335
|
+
- **Entity Framework**: Works with any BaseEntity subclass from `@memberjunction/core`
|
|
336
|
+
- **Metadata System**: Compatible with entities loaded through the MJ metadata system
|
|
337
|
+
- **Container Directives**: Uses `mjFillContainer` directive for proper layout integration
|
|
338
|
+
- **RunView**: Designed to work with records loaded via RunView queries
|
|
339
|
+
|
|
340
|
+
## Common Use Cases
|
|
341
|
+
|
|
342
|
+
1. **User Role Assignment**: Select users to assign to specific roles
|
|
343
|
+
2. **Permission Management**: Choose permissions to grant to users or roles
|
|
344
|
+
3. **Category Assignment**: Assign items to multiple categories
|
|
345
|
+
4. **Team Membership**: Manage team member selections
|
|
346
|
+
5. **Feature Selection**: Enable/disable features for specific tenants
|
|
347
|
+
|
|
348
|
+
## Best Practices
|
|
349
|
+
|
|
350
|
+
1. **Data Loading**: Always use the MemberJunction RunView pattern with `ResultType: 'entity_object'` for optimal performance
|
|
351
|
+
2. **Memory Management**: The dialog component maintains state internally, so you don't need to manage temporary arrays
|
|
352
|
+
3. **Field Names**: Ensure DisplayField matches actual property names in your entities (not the Get() method parameters)
|
|
353
|
+
4. **Icon Fields**: If using DisplayIconField, ensure the field contains valid CSS class names (e.g., 'fa-user', 'fas fa-star')
|
|
354
|
+
5. **Array References**: The component modifies the input arrays in place, so use the same array references throughout your component's lifecycle
|
|
355
|
+
|
|
356
|
+
## Troubleshooting
|
|
357
|
+
|
|
358
|
+
### Records not displaying
|
|
359
|
+
- Verify that DisplayField matches an actual property name in your BaseEntity objects
|
|
360
|
+
- Check that AvailableRecords is populated with valid BaseEntity instances
|
|
361
|
+
- Ensure SelectedRecords and UnselectedRecords are subsets of AvailableRecords
|
|
362
|
+
|
|
363
|
+
### Icons not showing
|
|
364
|
+
- Confirm DisplayIconField contains valid CSS class names
|
|
365
|
+
- Ensure required icon fonts (Font Awesome, etc.) are loaded in your application
|
|
366
|
+
|
|
367
|
+
### Dialog state issues
|
|
368
|
+
- Make sure DialogVisible is properly bound and updated
|
|
369
|
+
- Handle the DialogClosed event to update your component's state
|
|
370
|
+
|
|
371
|
+
## Version History
|
|
372
|
+
|
|
373
|
+
See [CHANGELOG.md](./CHANGELOG.md) for detailed version history.
|
|
374
|
+
|
|
375
|
+
## License
|
|
376
|
+
|
|
377
|
+
ISC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-record-selector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"description": "MemberJunction: Angular Components to allow a user to select/deselect items from a possible set",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"@progress/kendo-angular-listbox": "16.2.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@memberjunction/core-entities": "2.
|
|
32
|
-
"@memberjunction/global": "2.
|
|
33
|
-
"@memberjunction/core": "2.
|
|
34
|
-
"@memberjunction/ng-container-directives": "2.
|
|
35
|
-
"@memberjunction/ng-shared": "2.
|
|
31
|
+
"@memberjunction/core-entities": "2.44.0",
|
|
32
|
+
"@memberjunction/global": "2.44.0",
|
|
33
|
+
"@memberjunction/core": "2.44.0",
|
|
34
|
+
"@memberjunction/ng-container-directives": "2.44.0",
|
|
35
|
+
"@memberjunction/ng-shared": "2.44.0",
|
|
36
36
|
"tslib": "^2.3.0"
|
|
37
37
|
},
|
|
38
38
|
"sideEffects": false
|