@memberjunction/ng-find-record 4.0.0 → 4.1.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.
Files changed (2) hide show
  1. package/README.md +56 -277
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -1,22 +1,6 @@
1
1
  # @memberjunction/ng-find-record
2
2
 
3
- An Angular component library for searching and selecting records from any MemberJunction entity. This package provides both a standalone search component and a dialog wrapper component for easy integration into Angular applications.
4
-
5
- ## Purpose and Overview
6
-
7
- The `@memberjunction/ng-find-record` package simplifies the process of implementing entity record search functionality in MemberJunction-based Angular applications. It provides a reusable component that can search any entity using the MemberJunction metadata system and RunView API, displaying results in a Kendo UI grid for easy selection.
8
-
9
- ## Features
10
-
11
- - **Entity-Agnostic**: Works with any MemberJunction entity without modification
12
- - **Debounced Search**: Real-time search with configurable debounce time (default: 300ms)
13
- - **Grid Display**: Results displayed in a searchable, sortable Kendo UI grid
14
- - **Customizable Fields**: Configure which fields to display in the results grid
15
- - **Dialog Integration**: Optional dialog wrapper for modal usage scenarios
16
- - **Event Handling**: Events for record selection and dialog closure
17
- - **Loading States**: Visual feedback during search operations
18
- - **TypeScript Support**: Full TypeScript support with proper typing
19
- - **MemberJunction Integration**: Seamlessly integrates with MemberJunction's metadata and entity systems
3
+ An Angular component library for searching and selecting records from any MemberJunction entity. Provides both a standalone search component and a dialog wrapper for modal usage.
20
4
 
21
5
  ## Installation
22
6
 
@@ -24,27 +8,45 @@ The `@memberjunction/ng-find-record` package simplifies the process of implement
24
8
  npm install @memberjunction/ng-find-record
25
9
  ```
26
10
 
11
+ ## Overview
12
+
13
+ The Find Record package provides a reusable search interface that works with any entity registered in the MemberJunction metadata system. It uses debounced search input with the RunView API and displays results in a Kendo UI grid for easy selection.
14
+
15
+ ```mermaid
16
+ flowchart LR
17
+ subgraph Input["User Input"]
18
+ A["Search Text"] --> B["Debounce (300ms)"]
19
+ end
20
+ subgraph API["MJ Data Layer"]
21
+ B --> C["RunView + UserSearchString"]
22
+ C --> D["BaseEntity Results"]
23
+ end
24
+ subgraph Display["UI Components"]
25
+ D --> E["Kendo Grid"]
26
+ E --> F["OnRecordSelected"]
27
+ end
28
+
29
+ style Input fill:#2d6a9f,stroke:#1a4971,color:#fff
30
+ style API fill:#7c5295,stroke:#563a6b,color:#fff
31
+ style Display fill:#2d8659,stroke:#1a5c3a,color:#fff
32
+ ```
33
+
27
34
  ## Usage
28
35
 
29
- ### Import the Module
36
+ ### Module Import
30
37
 
31
38
  ```typescript
32
39
  import { FindRecordModule } from '@memberjunction/ng-find-record';
33
40
 
34
41
  @NgModule({
35
- imports: [
36
- FindRecordModule,
37
- // other imports
38
- ],
39
- // ...
42
+ imports: [FindRecordModule]
40
43
  })
41
- export class YourModule { }
44
+ export class YourModule {}
42
45
  ```
43
46
 
44
- ### Basic Component Usage
47
+ ### Standalone Search Component
45
48
 
46
49
  ```html
47
- <!-- Standalone search component -->
48
50
  <mj-find-record
49
51
  [EntityName]="'Users'"
50
52
  [SearchDebounceTime]="500"
@@ -52,16 +54,10 @@ export class YourModule { }
52
54
  </mj-find-record>
53
55
  ```
54
56
 
55
- ### Dialog Component Usage
57
+ ### Dialog Wrapper
56
58
 
57
59
  ```html
58
- <!-- Search component in a dialog -->
59
- <button kendoButton (click)="showFindDialog = true">
60
- Find User
61
- </button>
62
-
63
60
  <mj-find-record-dialog
64
- *ngIf="showFindDialog"
65
61
  [EntityName]="'Users'"
66
62
  [DialogTitle]="'Find User'"
67
63
  [DialogVisible]="showFindDialog"
@@ -70,277 +66,60 @@ export class YourModule { }
70
66
  </mj-find-record-dialog>
71
67
  ```
72
68
 
73
- ### TypeScript Component Example
69
+ ## Components
74
70
 
75
- ```typescript
76
- import { Component, OnInit } from '@angular/core';
77
- import { BaseEntity, EntityFieldInfo, Metadata } from '@memberjunction/core';
78
-
79
- @Component({
80
- selector: 'app-user-finder',
81
- template: `
82
- <h3>Find User</h3>
83
- <button kendoButton (click)="showDialog()">Open User Finder</button>
84
-
85
- <div *ngIf="selectedUser">
86
- <h4>Selected User:</h4>
87
- <p>{{ selectedUser.Get('UserName') }}</p>
88
- <p>{{ selectedUser.Get('Email') }}</p>
89
- </div>
90
-
91
- <mj-find-record-dialog
92
- *ngIf="dialogVisible"
93
- [EntityName]="'Users'"
94
- [DisplayFields]="displayFields"
95
- [DialogTitle]="'Find User'"
96
- [DialogVisible]="dialogVisible"
97
- [DialogWidth]="'800px'"
98
- [DialogHeight]="'500px'"
99
- (DialogClosed)="onDialogClosed($event)"
100
- (OnRecordSelected)="onUserSelected($event)">
101
- </mj-find-record-dialog>
102
- `
103
- })
104
- export class UserFinderComponent implements OnInit {
105
- dialogVisible = false;
106
- selectedUser: BaseEntity | null = null;
107
- displayFields: EntityFieldInfo[] = [];
108
-
109
- constructor(private metadata: Metadata) {}
110
-
111
- ngOnInit() {
112
- // Get specific fields to display in the grid
113
- const userEntity = this.metadata.EntityByName('Users');
114
- if (userEntity) {
115
- this.displayFields = [
116
- userEntity.Fields.find(f => f.Name === 'UserName')!,
117
- userEntity.Fields.find(f => f.Name === 'Email')!,
118
- userEntity.Fields.find(f => f.Name === 'FirstName')!,
119
- userEntity.Fields.find(f => f.Name === 'LastName')!
120
- ];
121
- }
122
- }
123
-
124
- showDialog() {
125
- this.dialogVisible = true;
126
- }
127
-
128
- onUserSelected(user: BaseEntity) {
129
- this.selectedUser = user;
130
- console.log('Selected user:', user);
131
- }
132
-
133
- onDialogClosed(confirmed: boolean) {
134
- this.dialogVisible = false;
135
-
136
- if (confirmed && this.selectedUser) {
137
- console.log('User selection confirmed:', this.selectedUser);
138
- // Do something with the selected user
139
- } else {
140
- console.log('User selection cancelled');
141
- }
142
- }
143
- }
144
- ```
145
-
146
- ## API Reference
71
+ | Component | Selector | Purpose |
72
+ |-----------|----------|---------|
73
+ | `FindRecordComponent` | `mj-find-record` | Standalone search with results grid |
74
+ | `FindRecordDialogComponent` | `mj-find-record-dialog` | Modal dialog wrapper around the search component |
147
75
 
148
76
  ### FindRecordComponent
149
77
 
150
- Standalone component for searching and selecting records. This component provides a search input with a grid display of results.
151
-
152
- #### Selector
153
- `mj-find-record`
154
-
155
78
  #### Inputs
156
79
 
157
80
  | Property | Type | Default | Description |
158
81
  |----------|------|---------|-------------|
159
- | `EntityName` | `string` | `''` | **Required.** The name of the MemberJunction entity to search |
160
- | `DisplayFields` | `EntityFieldInfo[]` | `[]` | Optional. Fields to display in the results grid. If not specified, defaults to fields marked as `DefaultInView`, `IsPrimaryKey`, `IsNameField`, or `IncludeInUserSearchAPI` |
161
- | `SearchDebounceTime` | `number` | `300` | Optional. Debounce time in milliseconds for search input |
82
+ | `EntityName` | `string` | `''` | Name of the MemberJunction entity to search |
83
+ | `DisplayFields` | `EntityFieldInfo[]` | `[]` | Fields to display in the results grid. Defaults to fields marked as `DefaultInView`, `IsPrimaryKey`, `IsNameField`, or `IncludeInUserSearchAPI` |
84
+ | `SearchDebounceTime` | `number` | `300` | Debounce time in milliseconds for search input |
162
85
 
163
86
  #### Outputs
164
87
 
165
88
  | Event | Type | Description |
166
89
  |-------|------|-------------|
167
- | `OnRecordSelected` | `EventEmitter<BaseEntity>` | Emitted when a user selects a record from the search results grid |
90
+ | `OnRecordSelected` | `EventEmitter<BaseEntity>` | Emitted when a user selects a record from the grid |
168
91
 
169
92
  ### FindRecordDialogComponent
170
93
 
171
- Dialog wrapper for the FindRecordComponent. Provides a modal dialog containing the search functionality.
172
-
173
- #### Selector
174
- `mj-find-record-dialog`
175
-
176
- #### Inputs
94
+ Inherits all inputs from `FindRecordComponent`, plus:
177
95
 
178
96
  | Property | Type | Default | Description |
179
97
  |----------|------|---------|-------------|
180
- | `EntityName` | `string` | `''` | **Required.** The name of the MemberJunction entity to search |
181
- | `DisplayFields` | `EntityFieldInfo[]` | `[]` | Optional. Fields to display in the results grid |
182
- | `DialogTitle` | `string` | `'Find Record'` | Optional. Title displayed in the dialog header |
183
- | `DialogWidth` | `string` | `'700px'` | Optional. Width of the dialog |
184
- | `DialogHeight` | `string` | `'450px'` | Optional. Height of the dialog |
185
- | `DialogVisible` | `boolean` | `false` | **Required.** Controls the visibility of the dialog |
186
- | `SelectedRecord` | `BaseEntity \| null` | `null` | Optional. Currently selected record. Can be set to pre-select a record |
187
-
188
- #### Outputs
98
+ | `DialogTitle` | `string` | `'Find Record'` | Title displayed in the dialog header |
99
+ | `DialogWidth` | `string` | `'700px'` | Width of the dialog |
100
+ | `DialogHeight` | `string` | `'450px'` | Height of the dialog |
101
+ | `DialogVisible` | `boolean` | `false` | Controls dialog visibility |
102
+ | `SelectedRecord` | `BaseEntity \| null` | `null` | Pre-selected record |
189
103
 
190
104
  | Event | Type | Description |
191
105
  |-------|------|-------------|
192
- | `DialogClosed` | `EventEmitter<boolean>` | Emitted when the dialog is closed. `true` if OK was clicked, `false` if cancelled |
193
- | `OnRecordSelected` | `EventEmitter<BaseEntity>` | Emitted when a user selects a record from the search results |
106
+ | `DialogClosed` | `EventEmitter<boolean>` | `true` if OK was clicked, `false` if cancelled |
194
107
 
195
108
  ## Search Behavior
196
109
 
197
- The component uses the MemberJunction RunView functionality with the following behavior:
198
-
199
- 1. As the user types in the search input, the input is debounced (default 300ms) to prevent excessive API calls
200
- 2. After the debounce period, a search is executed using `RunView` with the `UserSearchString` parameter
201
- 3. The search leverages MemberJunction's entity metadata to search across appropriate fields
202
- 4. Results are displayed in a Kendo UI grid with the specified or default fields
203
- 5. Users can select a record by clicking on a row in the grid
204
- 6. The selected record (as a `BaseEntity` instance) is emitted via the `OnRecordSelected` event
205
-
206
- ### Search Implementation Details
207
-
208
- The component uses the following RunView configuration:
209
- ```typescript
210
- {
211
- EntityName: this.EntityName,
212
- UserSearchString: searchTerm,
213
- ResultType: 'entity_object' // Returns BaseEntity instances
214
- }
215
- ```
216
-
217
- ## Styling
218
-
219
- The component includes basic CSS styling with the following classes:
220
- - `.find-textbox` - Styles the search input field
221
- - `.find-button` - Styles the Find button
222
-
223
- You can override these styles in your application's global styles or component-specific stylesheets.
110
+ 1. User types in the search input; input is debounced (default 300ms)
111
+ 2. A search executes via `RunView` with `UserSearchString` and `ResultType: 'entity_object'`
112
+ 3. Results display in a Kendo UI grid with the configured display fields
113
+ 4. Clicking a row emits the selected `BaseEntity` instance via `OnRecordSelected`
224
114
 
225
115
  ## Dependencies
226
116
 
227
- ### Production Dependencies
228
- - `@memberjunction/core`: ^2.43.0 - Core MemberJunction functionality including metadata, RunView, and BaseEntity
229
- - `@memberjunction/core-entities`: ^2.43.0 - Entity type definitions
230
- - `@memberjunction/global`: ^2.43.0 - Global utilities and helpers
231
- - `@memberjunction/ng-container-directives`: ^2.43.0 - Angular container directives
232
- - `@memberjunction/ng-shared`: ^2.43.0 - Shared Angular utilities
233
- - `rxjs`: ^7.8.1 - Reactive programming support for debouncing and search handling
234
- - `tslib`: ^2.3.0 - TypeScript runtime library
235
-
236
- ### Peer Dependencies (must be installed in your application)
237
- - `@angular/common`: 18.0.2
238
- - `@angular/core`: 18.0.2
239
- - `@angular/forms`: 18.0.2
240
- - `@angular/router`: 18.0.2
241
- - `@progress/kendo-angular-grid`: 16.2.0
242
- - `@progress/kendo-angular-buttons`: 16.2.0
243
- - `@progress/kendo-angular-inputs`: 16.2.0
244
- - `@progress/kendo-angular-dialog`: 16.2.0
245
- - `@progress/kendo-angular-listbox`: 16.2.0
246
-
247
- ## Integration with MemberJunction
248
-
249
- This package is designed to work seamlessly with the MemberJunction ecosystem:
250
-
251
- 1. **Metadata Integration**: Uses MemberJunction's Metadata class to retrieve entity information and field definitions
252
- 2. **Entity System**: Works with any entity registered in the MemberJunction metadata system
253
- 3. **RunView API**: Leverages the powerful RunView API for searching, which respects entity permissions and field-level security
254
- 4. **BaseEntity**: Returns actual BaseEntity instances, allowing full access to entity methods and properties
255
-
256
- ## Build and Development
257
-
258
- This package is part of the MemberJunction monorepo. To build:
259
-
260
- ```bash
261
- # From the package directory
262
- npm run build
263
-
264
- # Or from the monorepo root
265
- turbo build --filter="@memberjunction/ng-find-record"
266
- ```
267
-
268
- The package uses Angular's `ngc` compiler for building Angular libraries.
269
-
270
- ## Module Configuration
271
-
272
- The package exports a `FindRecordModule` that includes both components. Import this module in your Angular application:
273
-
274
- ```typescript
275
- import { FindRecordModule } from '@memberjunction/ng-find-record';
276
-
277
- @NgModule({
278
- imports: [
279
- FindRecordModule,
280
- // ... other imports
281
- ]
282
- })
283
- export class YourFeatureModule { }
284
- ```
285
-
286
- ## Advanced Usage
287
-
288
- ### Custom Field Selection
289
-
290
- You can programmatically select which fields to display based on your requirements:
291
-
292
- ```typescript
293
- // Display only specific fields
294
- const entity = this.metadata.EntityByName('Products');
295
- this.displayFields = entity.Fields.filter(f =>
296
- ['Name', 'SKU', 'Price', 'Category'].includes(f.Name)
297
- );
298
- ```
299
-
300
- ### Pre-selecting Records
301
-
302
- You can pre-select a record in the dialog component:
303
-
304
- ```typescript
305
- // Load a record and pre-select it
306
- const md = new Metadata();
307
- const user = await md.GetEntityObject<UserEntity>('Users');
308
- await user.Load(userId);
309
- this.selectedRecord = user;
310
- ```
311
-
312
- ### Handling Selection Events
313
-
314
- Process selected records with full type safety:
315
-
316
- ```typescript
317
- onRecordSelected(record: BaseEntity) {
318
- // Cast to specific entity type if needed
319
- if (record.EntityInfo.Name === 'Users') {
320
- const user = record as UserEntity;
321
- console.log('Selected user email:', user.Email);
322
- }
323
-
324
- // Or use generic BaseEntity methods
325
- console.log('Selected record ID:', record.Get('ID'));
326
- console.log('Selected record name:', record.Get(record.EntityInfo.NameField));
327
- }
328
- ```
329
-
330
- ## Error Handling
331
-
332
- The component includes built-in error handling:
333
-
334
- - Failed searches will log errors using MemberJunction's `LogError` function
335
- - Loading states provide visual feedback during searches
336
- - Empty search results display a user-friendly message
337
-
338
- ## Performance Considerations
339
-
340
- - **Debouncing**: The default 300ms debounce prevents excessive API calls during typing
341
- - **Entity Objects**: Using `ResultType: 'entity_object'` in RunView ensures efficient object creation
342
- - **Grid Virtualization**: The Kendo Grid component provides built-in virtualization for large result sets
117
+ - [@memberjunction/core](../../MJCore/README.md) -- Metadata, RunView, BaseEntity
118
+ - [@memberjunction/core-entities](../../MJCoreEntities/README.md) -- Entity type definitions
119
+ - [@memberjunction/ng-shared](../shared/README.md) -- Shared Angular utilities
120
+ - `@progress/kendo-angular-grid` -- Grid display
343
121
 
344
- ## License
122
+ ## Related Packages
345
123
 
346
- This package is part of the MemberJunction open-source project. See the root repository for license information.
124
+ - [@memberjunction/ng-record-selector](../record-selector/README.md) -- Dual-listbox record selection
125
+ - [@memberjunction/ng-generic-dialog](../generic-dialog/README.md) -- Reusable dialog component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-find-record",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "MemberJunction: Angular Component to allow a user to find a single record in any entity",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -30,11 +30,11 @@
30
30
  "@progress/kendo-angular-listbox": "22.0.1"
31
31
  },
32
32
  "dependencies": {
33
- "@memberjunction/core-entities": "4.0.0",
34
- "@memberjunction/global": "4.0.0",
35
- "@memberjunction/core": "4.0.0",
36
- "@memberjunction/ng-container-directives": "4.0.0",
37
- "@memberjunction/ng-shared": "4.0.0",
33
+ "@memberjunction/core-entities": "4.1.0",
34
+ "@memberjunction/global": "4.1.0",
35
+ "@memberjunction/core": "4.1.0",
36
+ "@memberjunction/ng-container-directives": "4.1.0",
37
+ "@memberjunction/ng-shared": "4.1.0",
38
38
  "rxjs": "^7.8.2",
39
39
  "tslib": "^2.8.1"
40
40
  },