@memberjunction/ng-record-selector 2.32.1 → 2.33.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 +250 -0
- package/package.json +6 -6
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Record Selector Component
|
|
2
|
+
|
|
3
|
+
An Angular component for selecting records from a list of available items in MemberJunction applications. This package provides both a standalone selection component and a dialog wrapper component for easy integration.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Dual Listbox Interface**: Easy selection between available and selected items
|
|
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
|
+
- **Memory Management**: Maintains selection state within dialog sessions
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @memberjunction/ng-record-selector
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Import the Module
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { RecordSelectorModule } from '@memberjunction/ng-record-selector';
|
|
28
|
+
|
|
29
|
+
@NgModule({
|
|
30
|
+
imports: [
|
|
31
|
+
RecordSelectorModule,
|
|
32
|
+
// other imports
|
|
33
|
+
],
|
|
34
|
+
// ...
|
|
35
|
+
})
|
|
36
|
+
export class YourModule { }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Basic Component Usage
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<!-- Standalone selector component -->
|
|
43
|
+
<mj-record-selector
|
|
44
|
+
[EntityName]="'Users'"
|
|
45
|
+
[DisplayField]="'UserName'"
|
|
46
|
+
[DisplayIconField]="'UserIcon'"
|
|
47
|
+
[AvailableRecords]="allUsers"
|
|
48
|
+
[SelectedRecords]="selectedUsers"
|
|
49
|
+
[UnselectedRecords]="unselectedUsers"
|
|
50
|
+
(RecordSelected)="onUserSelected($event)"
|
|
51
|
+
(RecordUnselected)="onUserUnselected($event)">
|
|
52
|
+
</mj-record-selector>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Dialog Component Usage
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<!-- Selector component in a dialog -->
|
|
59
|
+
<button kendoButton (click)="showSelectorDialog = true">
|
|
60
|
+
Select Users
|
|
61
|
+
</button>
|
|
62
|
+
|
|
63
|
+
<mj-record-selector-dialog
|
|
64
|
+
*ngIf="showSelectorDialog"
|
|
65
|
+
[EntityName]="'Users'"
|
|
66
|
+
[DisplayField]="'UserName'"
|
|
67
|
+
[AvailableRecords]="allUsers"
|
|
68
|
+
[SelectedRecords]="selectedUsers"
|
|
69
|
+
[UnselectedRecords]="unselectedUsers"
|
|
70
|
+
[DialogTitle]="'Select Users'"
|
|
71
|
+
[DialogVisible]="showSelectorDialog"
|
|
72
|
+
(DialogClosed)="onDialogClosed($event)"
|
|
73
|
+
(RecordSelected)="onUserSelected($event)"
|
|
74
|
+
(RecordUnselected)="onUserUnselected($event)">
|
|
75
|
+
</mj-record-selector-dialog>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### TypeScript Component Example
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { Component, OnInit } from '@angular/core';
|
|
82
|
+
import { BaseEntity, Metadata, RunView } from '@memberjunction/core';
|
|
83
|
+
import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
|
|
84
|
+
|
|
85
|
+
@Component({
|
|
86
|
+
selector: 'app-user-role-assignment',
|
|
87
|
+
template: `
|
|
88
|
+
<h3>Assign Users to Role</h3>
|
|
89
|
+
<button kendoButton (click)="openUserSelector()">Select Users</button>
|
|
90
|
+
|
|
91
|
+
<div *ngIf="selectedUsers.length > 0">
|
|
92
|
+
<h4>Selected Users ({{ selectedUsers.length }}):</h4>
|
|
93
|
+
<ul>
|
|
94
|
+
<li *ngFor="let user of selectedUsers">
|
|
95
|
+
{{ user.Get('UserName') }} - {{ user.Get('Email') }}
|
|
96
|
+
</li>
|
|
97
|
+
</ul>
|
|
98
|
+
<button kendoButton (click)="saveUserAssignments()">Save Assignments</button>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<mj-record-selector-dialog
|
|
102
|
+
*ngIf="selectorDialogVisible"
|
|
103
|
+
[EntityName]="'Users'"
|
|
104
|
+
[DisplayField]="'UserName'"
|
|
105
|
+
[DisplayIconField]="'UserIcon'"
|
|
106
|
+
[AvailableRecords]="allUsers"
|
|
107
|
+
[SelectedRecords]="selectedUsers"
|
|
108
|
+
[UnselectedRecords]="unselectedUsers"
|
|
109
|
+
[ToolbarSettings]="toolbarSettings"
|
|
110
|
+
[DialogTitle]="'Select Users for Role'"
|
|
111
|
+
[DialogVisible]="selectorDialogVisible"
|
|
112
|
+
[DialogWidth]="'800px'"
|
|
113
|
+
[DialogHeight]="'600px'"
|
|
114
|
+
(DialogClosed)="onSelectorDialogClosed($event)">
|
|
115
|
+
</mj-record-selector-dialog>
|
|
116
|
+
`
|
|
117
|
+
})
|
|
118
|
+
export class UserRoleAssignmentComponent implements OnInit {
|
|
119
|
+
allUsers: BaseEntity[] = [];
|
|
120
|
+
selectedUsers: BaseEntity[] = [];
|
|
121
|
+
unselectedUsers: BaseEntity[] = [];
|
|
122
|
+
selectorDialogVisible = false;
|
|
123
|
+
|
|
124
|
+
toolbarSettings: ListBoxToolbarConfig = {
|
|
125
|
+
position: "right",
|
|
126
|
+
tools: ["transferFrom", "transferAllFrom", "transferAllTo", "transferTo"]
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
constructor(private metadata: Metadata) {}
|
|
130
|
+
|
|
131
|
+
async ngOnInit() {
|
|
132
|
+
await this.loadUsers();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async loadUsers() {
|
|
136
|
+
// Load all users
|
|
137
|
+
const rv = new RunView();
|
|
138
|
+
const result = await rv.RunView({
|
|
139
|
+
EntityName: 'Users',
|
|
140
|
+
ResultType: 'entity_object'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (result.Success) {
|
|
144
|
+
this.allUsers = result.Results;
|
|
145
|
+
// Initially all users are unselected
|
|
146
|
+
this.unselectedUsers = [...this.allUsers];
|
|
147
|
+
this.selectedUsers = [];
|
|
148
|
+
} else {
|
|
149
|
+
console.error('Failed to load users:', result.ErrorMessage);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
openUserSelector() {
|
|
154
|
+
this.selectorDialogVisible = true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
onSelectorDialogClosed(confirmed: boolean) {
|
|
158
|
+
this.selectorDialogVisible = false;
|
|
159
|
+
|
|
160
|
+
if (confirmed) {
|
|
161
|
+
console.log('User selection confirmed:', this.selectedUsers);
|
|
162
|
+
} else {
|
|
163
|
+
console.log('User selection cancelled');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
saveUserAssignments() {
|
|
168
|
+
// Logic to save user role assignments
|
|
169
|
+
console.log('Saving role assignments for users:', this.selectedUsers);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Reference
|
|
175
|
+
|
|
176
|
+
### RecordSelectorComponent
|
|
177
|
+
|
|
178
|
+
Standalone component for selecting records.
|
|
179
|
+
|
|
180
|
+
#### Inputs
|
|
181
|
+
|
|
182
|
+
- `EntityName`: string - The name of the entity to show records for
|
|
183
|
+
- `DisplayField`: string - The field name to display in the list items
|
|
184
|
+
- `DisplayIconField`: string - The field name containing CSS class for icons (optional)
|
|
185
|
+
- `AvailableRecords`: BaseEntity[] - List of all available records
|
|
186
|
+
- `SelectedRecords`: BaseEntity[] - List of selected records
|
|
187
|
+
- `UnselectedRecords`: BaseEntity[] - List of unselected records
|
|
188
|
+
- `ToolbarSettings`: ListBoxToolbarConfig - Configuration for the listbox toolbar
|
|
189
|
+
|
|
190
|
+
#### Outputs
|
|
191
|
+
|
|
192
|
+
- `RecordSelected`: EventEmitter<BaseEntity[]> - Emitted when records are selected
|
|
193
|
+
- `RecordUnselected`: EventEmitter<BaseEntity[]> - Emitted when records are unselected
|
|
194
|
+
|
|
195
|
+
### RecordSelectorDialogComponent
|
|
196
|
+
|
|
197
|
+
Dialog wrapper for the RecordSelectorComponent.
|
|
198
|
+
|
|
199
|
+
#### Inputs
|
|
200
|
+
|
|
201
|
+
- All inputs from RecordSelectorComponent, plus:
|
|
202
|
+
- `DialogTitle`: string - Title of the dialog (default: 'Select Records')
|
|
203
|
+
- `DialogWidth`: string - Width of the dialog (default: '700px')
|
|
204
|
+
- `DialogHeight`: string - Height of the dialog (default: '450px')
|
|
205
|
+
- `DialogVisible`: boolean - Controls the visibility of the dialog
|
|
206
|
+
|
|
207
|
+
#### Outputs
|
|
208
|
+
|
|
209
|
+
- All outputs from RecordSelectorComponent, plus:
|
|
210
|
+
- `DialogClosed`: EventEmitter<boolean> - Emitted when the dialog is closed (true if confirmed, false if canceled)
|
|
211
|
+
|
|
212
|
+
## Toolbar Configuration
|
|
213
|
+
|
|
214
|
+
The component accepts a `ListBoxToolbarConfig` object to customize the available toolbar actions:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
const toolbarSettings: ListBoxToolbarConfig = {
|
|
218
|
+
position: "right", // or "left", "top", "bottom"
|
|
219
|
+
tools: [
|
|
220
|
+
"moveUp", // Move selected item up
|
|
221
|
+
"transferFrom", // Move selected item from unselected to selected
|
|
222
|
+
"transferAllFrom", // Move all items from unselected to selected
|
|
223
|
+
"transferAllTo", // Move all items from selected to unselected
|
|
224
|
+
"transferTo", // Move selected item from selected to unselected
|
|
225
|
+
"moveDown" // Move selected item down
|
|
226
|
+
]
|
|
227
|
+
};
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Selection Behavior
|
|
231
|
+
|
|
232
|
+
The component uses Kendo UI ListBox components with the following behavior:
|
|
233
|
+
|
|
234
|
+
1. Items can be moved between lists using the toolbar buttons
|
|
235
|
+
2. Items can be dragged and dropped between lists
|
|
236
|
+
3. Double-clicking an item moves it to the other list
|
|
237
|
+
4. When used in a dialog, changes are only committed when the OK button is clicked; Cancel reverts to the previous state
|
|
238
|
+
|
|
239
|
+
## Styling
|
|
240
|
+
|
|
241
|
+
The component uses Kendo UI ListBox component styles and includes basic CSS that can be overridden in your application.
|
|
242
|
+
|
|
243
|
+
## Dependencies
|
|
244
|
+
|
|
245
|
+
- `@memberjunction/core`: For metadata and entity types
|
|
246
|
+
- `@memberjunction/core-entities`: For entity types
|
|
247
|
+
- `@memberjunction/global`: For global utilities
|
|
248
|
+
- `@progress/kendo-angular-listbox`: For the list box component
|
|
249
|
+
- `@progress/kendo-angular-buttons`: For UI buttons
|
|
250
|
+
- `@progress/kendo-angular-dialog`: For dialog wrapper
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-record-selector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.33.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.33.0",
|
|
32
|
+
"@memberjunction/global": "2.33.0",
|
|
33
|
+
"@memberjunction/core": "2.33.0",
|
|
34
|
+
"@memberjunction/ng-container-directives": "2.33.0",
|
|
35
|
+
"@memberjunction/ng-shared": "2.33.0",
|
|
36
36
|
"tslib": "^2.3.0"
|
|
37
37
|
},
|
|
38
38
|
"sideEffects": false
|