powerpagestoolkit 2.221.12 → 2.701.4
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 +421 -230
- package/dist/import_map.json +6 -0
- package/dist/src/constants/eventMapping.d.ts +7 -0
- package/dist/src/constants/symbols.d.ts +14 -0
- package/dist/{API.d.ts → src/core/API.d.ts} +16 -8
- package/dist/src/core/DOMNodeReference.d.ts +227 -0
- package/dist/src/core/DOMNodeReferenceArray.d.ts +12 -0
- package/dist/src/core/List.d.ts +13 -0
- package/dist/src/core/bindForm.d.ts +28 -0
- package/dist/src/core/createDOMNodeReferences.d.ts +88 -0
- package/dist/src/core/waitFor.d.ts +9 -0
- package/dist/{errors.d.ts → src/errors/errors.d.ts} +5 -1
- package/dist/src/globals.d.ts +152 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +1251 -0
- package/dist/src/index.js.LEGAL.txt +0 -0
- package/dist/src/index.js.map +7 -0
- package/dist/src/managers/ReferenceManager.d.ts +6 -0
- package/dist/src/utils/createInfoElement.d.ts +8 -0
- package/dist/src/utils/enhanceArray.d.ts +13 -0
- package/dist/src/utils/safeAjax.d.ts +5 -0
- package/package.json +42 -29
- package/dist/DOMNodeReference.d.ts +0 -197
- package/dist/bundle.js +0 -704
- package/dist/createDOMNodeReferences.d.ts +0 -15
- package/dist/createInfoElement.d.ts +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/safeAjax.d.ts +0 -1
- package/dist/waitFor.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,317 +1,508 @@
|
|
|
1
1
|
# PowerPages Tool Kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A TypeScript/JavaScript utility package for seamless DOM manipulation and DataVerse API interactions in PowerPages applications. This toolkit provides robust DOM element management and standardized DataVerse CRUD operations with full TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Powerful DOM element manipulation and reference management
|
|
8
|
+
- Type-safe DataVerse API operations
|
|
9
|
+
- Automatic value synchronization for form elements
|
|
10
|
+
- Advanced conditional rendering and validation
|
|
11
|
+
- Radio button and checkbox handling
|
|
12
|
+
- Event management with proper TypeScript typing
|
|
13
|
+
- Mutation observer integration for dynamic content
|
|
14
|
+
- Tooltip and label management utilities
|
|
4
15
|
|
|
5
16
|
## Installation
|
|
6
17
|
|
|
7
|
-
|
|
18
|
+
```bash
|
|
19
|
+
npm install powerpagestoolkit
|
|
20
|
+
```
|
|
8
21
|
|
|
9
|
-
|
|
22
|
+
# Core Modules
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
### DOMNodeReference
|
|
12
25
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
A powerful class for managing DOM elements with automatic value synchronization and event handling.
|
|
27
|
+
|
|
28
|
+
#### Basic Usage
|
|
29
|
+
|
|
30
|
+
DOMNodeReferences are instantiated with the help of the following factory function: `createRef`
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
createRef(
|
|
34
|
+
target: HTMLElement | string,
|
|
35
|
+
options: {
|
|
36
|
+
multiple: (() => boolean) | boolean = false,
|
|
37
|
+
root: HTMLElement,
|
|
38
|
+
timeoutMs:number
|
|
39
|
+
}
|
|
40
|
+
): Promise<DOMNodeReference | DOMNodeReference[]>;
|
|
19
41
|
```
|
|
20
42
|
|
|
21
|
-
|
|
43
|
+
createRef takes two main arguments:
|
|
44
|
+
|
|
45
|
+
<table style="width: 100%; border-collapse: collapse;">
|
|
46
|
+
<thead>
|
|
47
|
+
<tr>
|
|
48
|
+
<th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Property</th>
|
|
49
|
+
<th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Type</th>
|
|
50
|
+
<th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Details</th>
|
|
51
|
+
</tr>
|
|
52
|
+
</thead>
|
|
53
|
+
<tbody>
|
|
54
|
+
<tr>
|
|
55
|
+
<td style="border: 1px solid #ddd; padding: 8px;">target</td>
|
|
56
|
+
<td style="border: 1px solid #ddd; padding: 8px;">
|
|
57
|
+
<pre><code class="language-javascript">string | HTMLElement</code></pre>
|
|
58
|
+
</td>
|
|
59
|
+
<td style="border: 1px solid #ddd; padding: 8px;">
|
|
60
|
+
Use standard <code>querySelector</code> syntax to target an element, or elements in the DOM, or pass in an instance of the element itself to create a reference.
|
|
61
|
+
</td>
|
|
62
|
+
</tr>
|
|
63
|
+
<tr>
|
|
64
|
+
<td style="border: 1px solid #ddd; padding: 8px;">options</td>
|
|
65
|
+
<td style="border: 1px solid #ddd; padding: 8px;">
|
|
66
|
+
<pre><code class="language-javascript">{
|
|
67
|
+
multiple: () => boolean | boolean,
|
|
68
|
+
root: HTMLElement,
|
|
69
|
+
timeoutMs:number
|
|
70
|
+
}</code></pre>
|
|
71
|
+
</td>
|
|
72
|
+
<td style="border: 1px solid #ddd; padding: 8px;">
|
|
73
|
+
Provides advanced configurations for niche scenarios, such as async DOM element loading, returning arrays of elements, or specifying the parent to search within for the target node.
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
</tbody>
|
|
77
|
+
</table>
|
|
78
|
+
|
|
79
|
+
Import the utility function for creating DOMNodeReference(s)
|
|
22
80
|
|
|
23
|
-
|
|
81
|
+
```typescript
|
|
82
|
+
import { createRef } from "powerpagestoolkit";
|
|
83
|
+
```
|
|
24
84
|
|
|
25
|
-
|
|
85
|
+
Instantiate one, or multiple instances of a DOMNodeReference, and optionally configure advanced options
|
|
26
86
|
|
|
27
|
-
|
|
87
|
+
```javascript
|
|
88
|
+
// Create a single reference (i.e. 'querySelector')
|
|
89
|
+
const node = await createRef("#myElement");
|
|
90
|
+
|
|
91
|
+
// Create multiple references (i.e. 'querySelectorAll')
|
|
92
|
+
const nodes = await createRef(".my-class", { multiple: true });
|
|
93
|
+
|
|
94
|
+
/******************/
|
|
95
|
+
// ADVANCED OPTIONS
|
|
96
|
+
// in the event that you need to be more granular with how you are targeting
|
|
97
|
+
// and retrieving elements, there are additional options
|
|
98
|
+
|
|
99
|
+
// If the node you are targeting is not available at the initial execution
|
|
100
|
+
// of the script, set a timeout for 2 seconds
|
|
101
|
+
const node2 = await createRef("#target", { timeoutMs:2000 });
|
|
102
|
+
|
|
103
|
+
// need to target a node within a specific node? use that node as the root
|
|
104
|
+
const otherElement = document.getElementById("id");
|
|
105
|
+
const node3 = await createRef("#target", { root: otherElement });
|
|
106
|
+
|
|
107
|
+
// implement all options:
|
|
108
|
+
const nodes2 = await createRef("#target", {
|
|
109
|
+
multiple: true,
|
|
110
|
+
timeoutMs:4000,
|
|
111
|
+
root: otherElement,
|
|
112
|
+
});
|
|
113
|
+
```
|
|
28
114
|
|
|
29
|
-
|
|
115
|
+
#### Properties
|
|
30
116
|
|
|
31
|
-
|
|
117
|
+
| Property | Type | Description |
|
|
118
|
+
| -------- | ------------------------ | --------------------------------------------- |
|
|
119
|
+
| element | HTMLElement | The referenced DOM element |
|
|
120
|
+
| value | any | Current synchronized value of the element |
|
|
121
|
+
| isLoaded | boolean | Element load status |
|
|
122
|
+
| target | HTMLElement \| string | Original target selector or element |
|
|
123
|
+
| yesRadio | DOMNodeReference \| null | Reference to 'yes' radio (for boolean fields) |
|
|
124
|
+
| noRadio | DOMNodeReference \| null | Reference to 'no' radio (for boolean fields) |
|
|
125
|
+
| checked | boolean | Checkbox/radio checked state |
|
|
32
126
|
|
|
33
|
-
|
|
127
|
+
#### Key Methods
|
|
34
128
|
|
|
35
|
-
|
|
36
|
-
// single instance of DOMNodeReference
|
|
37
|
-
const node = await createDOMNodeReference("#my-element");
|
|
129
|
+
##### Event Handling
|
|
38
130
|
|
|
39
|
-
|
|
40
|
-
|
|
131
|
+
```typescript
|
|
132
|
+
// Add event listener with proper 'this' context
|
|
133
|
+
// uses standard eventListener API, and so supports all DOM events
|
|
134
|
+
node.on("change", function (e) {
|
|
135
|
+
console.log("Current value:", this.value);
|
|
41
136
|
});
|
|
42
137
|
|
|
43
|
-
|
|
44
|
-
|
|
138
|
+
node.on("click", function (e) {
|
|
139
|
+
console.log(this, " has been clicked");
|
|
140
|
+
});
|
|
45
141
|
|
|
46
|
-
|
|
47
|
-
node.oneLoaded(() => {
|
|
48
|
-
console.log("Element loaded: ", node.element")
|
|
49
|
-
})
|
|
50
|
-
})
|
|
142
|
+
...
|
|
51
143
|
```
|
|
52
144
|
|
|
53
|
-
#####
|
|
145
|
+
##### Business Rule Application
|
|
146
|
+
|
|
147
|
+
This utility provides a flexible way to dynamically control field visibility, requirement status, values, and enabled states based on dependencies within PowerPages forms.
|
|
54
148
|
|
|
55
|
-
|
|
149
|
+
_Method Signature:_
|
|
56
150
|
|
|
57
151
|
```typescript
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* If the element targeted is the main input for a yes/no radio control,
|
|
64
|
-
* yesRadio and noRadio will be available as properties of 'this'
|
|
65
|
-
*/
|
|
66
|
-
yesRadio: DOMNodeReference;
|
|
67
|
-
noRadio: DOMNodeReference;
|
|
68
|
-
// and if 'this' is the instance of a yesRadio or noRadio
|
|
69
|
-
// checked will represent wether the radio has been checked or not
|
|
70
|
-
checked: boolean;
|
|
152
|
+
applyBusinessRule(
|
|
153
|
+
rule: BusinessRule,
|
|
154
|
+
dependencies: DOMNodeReference[]
|
|
155
|
+
): DOMNodeReference; /* Instance of this is returned for optional
|
|
156
|
+
method chaining */
|
|
71
157
|
```
|
|
72
158
|
|
|
73
|
-
|
|
159
|
+
**BusinessRule Definition**
|
|
74
160
|
|
|
75
|
-
|
|
161
|
+
```typescript
|
|
162
|
+
interface BusinessRule {
|
|
163
|
+
setVisibility?: [
|
|
164
|
+
condition: () => boolean,
|
|
165
|
+
clearValuesOnHide?: boolean = true
|
|
166
|
+
];
|
|
167
|
+
setRequired?: [
|
|
168
|
+
isRequired: () => boolean,
|
|
169
|
+
isValid: () => boolean
|
|
170
|
+
];
|
|
171
|
+
setValue?: [
|
|
172
|
+
condition: () => boolean,
|
|
173
|
+
value: () => any | any
|
|
174
|
+
];
|
|
175
|
+
setDisabled?: () => boolean;
|
|
176
|
+
}
|
|
177
|
+
```
|
|
76
178
|
|
|
77
|
-
|
|
179
|
+
##### Visibility Control
|
|
78
180
|
|
|
79
|
-
|
|
80
|
-
//
|
|
181
|
+
```typescript
|
|
182
|
+
// Show the 'taxIdField' only when
|
|
183
|
+
// 'businessTypeField' is set to 'Corporation' or 'LLC'
|
|
184
|
+
taxIdField.applyBusinessRule(
|
|
185
|
+
{
|
|
186
|
+
setVisibility: [
|
|
187
|
+
() =>
|
|
188
|
+
businessTypeField.value === "Corporation" ||
|
|
189
|
+
businessTypeField.value === "LLC",
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
[businessTypeField] // Re-evaluate when businessTypeField changes
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// Optionally disable 'clearValuesOnHide':
|
|
196
|
+
taxIdField.applyBusinessRule(
|
|
197
|
+
{
|
|
198
|
+
setVisibility: [
|
|
199
|
+
() =>
|
|
200
|
+
businessTypeField.value === "Corporation" ||
|
|
201
|
+
businessTypeField.value === "LLC",
|
|
202
|
+
false, // defaults to true. False will prevent the fields from losing it's value if it is hidden
|
|
203
|
+
],
|
|
204
|
+
},
|
|
205
|
+
[businessTypeField] // Re-evaluate when businessTypeField changes
|
|
206
|
+
);
|
|
207
|
+
```
|
|
81
208
|
|
|
82
|
-
|
|
83
|
-
hide()
|
|
209
|
+
##### Validation and Requirements
|
|
84
210
|
|
|
85
|
-
|
|
86
|
-
|
|
211
|
+
```typescript
|
|
212
|
+
// Require 'taxIdField' when 'businessTypeField' is 'Corporation' or 'LLC'
|
|
213
|
+
taxIdField.applyBusinessRule(
|
|
214
|
+
{
|
|
215
|
+
setRequired: [
|
|
216
|
+
function () {
|
|
217
|
+
return (
|
|
218
|
+
businessTypeField.value === "Corporation" ||
|
|
219
|
+
businessTypeField.value === "LLC"
|
|
220
|
+
);
|
|
221
|
+
},
|
|
222
|
+
function () {
|
|
223
|
+
return this.value != null && this.value !== "";
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
[businessTypeField] // Revalidate when businessTypeField changes
|
|
228
|
+
);
|
|
229
|
+
```
|
|
87
230
|
|
|
88
|
-
|
|
89
|
-
* advanced visibility control in the case you need to apply
|
|
90
|
-
* custom logic to the visibility of an element
|
|
91
|
-
*/
|
|
92
|
-
toggleVisibility(shouldShow: boolean | () => boolean)
|
|
231
|
+
##### Setting Field Values Conditionally
|
|
93
232
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* visibility of the target node.
|
|
107
|
-
*/
|
|
108
|
-
configureConditionalRendering(
|
|
109
|
-
condition: (this: DOMNodeReference) => boolean,
|
|
110
|
-
dependencies: Array<DOMNodeReference>
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// EXAMPLE:
|
|
115
|
-
const your_node = await createDOMNodeReference("#element_id")
|
|
116
|
-
const other_node = await createDOMNodeReference(".element_class")
|
|
117
|
-
|
|
118
|
-
your_node.configureConditionalRendering(() =>
|
|
119
|
-
other_node.value == "3",
|
|
120
|
-
/* your_node will only be
|
|
121
|
-
visible when the value of other_node is "3"
|
|
122
|
-
*/
|
|
123
|
-
[other_node]
|
|
124
|
-
/* and we have to include any DOMNodeReferences used
|
|
125
|
-
in the evaluation logic, so that changes to them can
|
|
126
|
-
be watched and the condition evaluated again
|
|
127
|
-
*/
|
|
128
|
-
);
|
|
233
|
+
```typescript
|
|
234
|
+
// Set default industry value when 'businessTypeField' is 'Corporation'
|
|
235
|
+
industryField.applyBusinessRule(
|
|
236
|
+
{
|
|
237
|
+
setValue: [
|
|
238
|
+
() => businessTypeField.value === "Corporation",
|
|
239
|
+
"Corporate"
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
[businessTypeField] // Apply value when businessTypeField changes
|
|
243
|
+
);
|
|
244
|
+
```
|
|
129
245
|
|
|
246
|
+
##### Enabling and Disabling Fields
|
|
130
247
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
* @param {function(this: DOMNodeReference): boolean} isValid
|
|
140
|
-
* A function that checks if the field's input is valid.
|
|
141
|
-
* Return `true` if validation satisfied, `false` if not.
|
|
142
|
-
* @param {string} fieldDisplayName - The name of the field, used
|
|
143
|
-
* in error messages if validation fails.
|
|
144
|
-
* @param {Array<DOMNodeReference>} [dependencies]
|
|
145
|
-
* Other fields that this field’s requirement depends on. When
|
|
146
|
-
* these Nodes or their values change, the required status
|
|
147
|
-
* of this field is re-evaluated. Make sure any DOMNodeReference
|
|
148
|
-
* used in `isRequired` or `isValid` is included in this array.
|
|
149
|
-
*/
|
|
150
|
-
configureValidationAndRequirements(
|
|
151
|
-
isRequired: (this: this) => boolean,
|
|
152
|
-
isValid: (this: this) => boolean,
|
|
153
|
-
fieldDisplayName: string,
|
|
154
|
-
dependencies: Array<DOMNodeReference>
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
// EXAMPLE:
|
|
158
|
-
const your_node = await createDOMNodeReference("#element_id")
|
|
159
|
-
const other_node = await createDOMNodeReference(".element_class")
|
|
160
|
-
|
|
161
|
-
your_node.configureValidationAndRequirements(
|
|
162
|
-
() => other_node.yesRadio.checked,
|
|
163
|
-
/* if 'yes' is checked for this other node,
|
|
164
|
-
this function will evaluate to true,
|
|
165
|
-
meaning that 'your_node' will be required */
|
|
166
|
-
|
|
167
|
-
function () {
|
|
168
|
-
/* important to use standard 'function' declaration,
|
|
169
|
-
instead of arrow function when needing to
|
|
170
|
-
access 'this' (the instance of 'your_node') */
|
|
171
|
-
|
|
172
|
-
if (other_node.yesRadio.checked) {
|
|
173
|
-
// when other_node radio is checked 'yes'
|
|
174
|
-
return this.value; // this is only 'valid' if it has a value
|
|
175
|
-
} else return true;
|
|
176
|
-
},
|
|
177
|
-
"Your Field Name",
|
|
178
|
-
[other_node]
|
|
179
|
-
/* since our conditions depend on
|
|
180
|
-
'other_node' it must be included in the dependency
|
|
181
|
-
array so that the requirement conditions can be
|
|
182
|
-
re-evaluated when the value of 'other_node' changes */
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
/* sets the elements 'disabled' to true - useful for inputs
|
|
187
|
-
that need to be enabled/disabled conditionally */
|
|
188
|
-
disable()
|
|
189
|
-
|
|
190
|
-
// Sets the element 'disabled' to false
|
|
191
|
-
enable()
|
|
248
|
+
```typescript
|
|
249
|
+
// Disable 'taxIdField' when 'businessTypeField' is 'Individual'
|
|
250
|
+
taxIdField.applyBusinessRule(
|
|
251
|
+
{
|
|
252
|
+
setDisabled: () => businessTypeField.value === "Individual",
|
|
253
|
+
},
|
|
254
|
+
[businessTypeField] // Enable/disable when businessTypeField changes
|
|
255
|
+
);
|
|
192
256
|
```
|
|
193
257
|
|
|
194
|
-
|
|
195
|
-
|
|
258
|
+
##### Element Manipulation
|
|
259
|
+
|
|
260
|
+
_Value management_
|
|
196
261
|
|
|
197
|
-
|
|
198
|
-
|
|
262
|
+
```typescript
|
|
263
|
+
// set a static value
|
|
264
|
+
node.setValue("new value");
|
|
265
|
+
|
|
266
|
+
// or set a value by using some sort of logic
|
|
267
|
+
node.setValue(() => {
|
|
268
|
+
if (true) {
|
|
269
|
+
return "value";
|
|
270
|
+
} else return "default";
|
|
271
|
+
});
|
|
199
272
|
|
|
200
|
-
//
|
|
201
|
-
|
|
273
|
+
// Sync with DOM
|
|
274
|
+
node.updateValue();
|
|
202
275
|
|
|
203
|
-
//
|
|
204
|
-
|
|
276
|
+
// Clear the value for both the instance and the target element
|
|
277
|
+
node.clearValue();
|
|
278
|
+
```
|
|
205
279
|
|
|
206
|
-
|
|
207
|
-
append(...elements: HTMLElement[])
|
|
280
|
+
_Content manipulation_
|
|
208
281
|
|
|
209
|
-
|
|
210
|
-
|
|
282
|
+
```typescript
|
|
283
|
+
node.setInnerHTML("<span>New content</span>");
|
|
284
|
+
node.append(childElement);
|
|
285
|
+
node.prepend(headerElement);
|
|
286
|
+
node.after(siblingElement);
|
|
287
|
+
node.before(labelElement);
|
|
288
|
+
```
|
|
211
289
|
|
|
212
|
-
|
|
213
|
-
getLabel(): HTMLElement | null
|
|
290
|
+
_Styling_
|
|
214
291
|
|
|
215
|
-
|
|
216
|
-
|
|
292
|
+
```typescript
|
|
293
|
+
node.setStyle({
|
|
294
|
+
display: "block",
|
|
295
|
+
color: "red",
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
_Enabling/Disabling inputs_
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
node.disable();
|
|
303
|
+
node.enable();
|
|
304
|
+
```
|
|
217
305
|
|
|
218
|
-
|
|
219
|
-
// in the event handler function
|
|
220
|
-
on(eventType: string, eventHandler: (this: DOMNodeReference) => void)
|
|
306
|
+
##### Label and Tooltip Management
|
|
221
307
|
|
|
222
|
-
|
|
223
|
-
|
|
308
|
+
```typescript
|
|
309
|
+
// LABEL AND INFO OPERATIONS
|
|
310
|
+
const label = node.getLabel();
|
|
311
|
+
// appends a tooltip to the label associated with the element targeted by 'this'
|
|
312
|
+
node.addLabelTooltip(
|
|
313
|
+
"Helper text",
|
|
314
|
+
/* Optionally pass in css styles to customize the tooltip icon*/
|
|
315
|
+
{ color: "orange", fontSize: "30px" }
|
|
316
|
+
);
|
|
317
|
+
// appends a tooltip directly to the element targeted by 'this'
|
|
318
|
+
node.addTooltip(
|
|
319
|
+
"Inline helper",
|
|
320
|
+
/* Optionally pass in css styles to customize the tooltip icon*/
|
|
321
|
+
{ color: "orange", fontSize: "30px" }
|
|
322
|
+
);
|
|
323
|
+
```
|
|
224
324
|
|
|
225
|
-
|
|
226
|
-
addLabelTooltip(text: string)
|
|
325
|
+
_Example:_
|
|
227
326
|
|
|
228
|
-
|
|
229
|
-
|
|
327
|
+
```typescript
|
|
328
|
+
import { createRef } from "powerpagestoolkit";
|
|
230
329
|
|
|
231
|
-
|
|
232
|
-
onceLoaded(callback: (instance: DOMNodeReference) => void)
|
|
330
|
+
const title = await createRef("#myTitle");
|
|
233
331
|
|
|
332
|
+
title.addTooltip("This is an Example of a tooltip!", { color: "red" });
|
|
234
333
|
```
|
|
235
334
|
|
|
236
|
-
|
|
335
|
+

|
|
336
|
+
|
|
337
|
+
Here's an improved markdown documentation with more comprehensive details:
|
|
338
|
+
|
|
339
|
+
### BindForm Method
|
|
237
340
|
|
|
238
|
-
The `
|
|
341
|
+
The `bindForm` method simplifies form element management in DataVerse by providing a semantic and efficient way to access form controls, sections, and tabs.
|
|
239
342
|
|
|
240
|
-
|
|
241
|
-
- **`getRecord(tableSetName, recordID, selectColumns)`**: Retrieves a specific record from the DataVerse. Returns a Promise that resolves with the retrieved record or rejects with an error.
|
|
343
|
+
##### Key Features
|
|
242
344
|
|
|
243
|
-
-
|
|
345
|
+
- Retrieves form definition directly from DataVerse
|
|
346
|
+
- Automatically generates references for:
|
|
347
|
+
- Controls
|
|
348
|
+
- Sections
|
|
349
|
+
- Tabs
|
|
244
350
|
|
|
245
|
-
|
|
351
|
+
##### Element Types
|
|
246
352
|
|
|
247
|
-
|
|
353
|
+
| Element Type | Description | Accessibility |
|
|
354
|
+
| ------------ | ------------------------------------------- | ------------------------- |
|
|
355
|
+
| `control` | Includes all form fields and sub-grids | Accessed via logical name |
|
|
356
|
+
| `section` | Standard PowerApps form sections | Accessed via logical name |
|
|
357
|
+
| `tab` | Form tabs corresponding to PowerApps layout | Accessed via logical name |
|
|
248
358
|
|
|
249
|
-
|
|
359
|
+
##### Usage Example
|
|
250
360
|
|
|
251
361
|
```javascript
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
362
|
+
import { bindForm } from "powerpagestoolkit";
|
|
363
|
+
|
|
364
|
+
// Basic form binding
|
|
365
|
+
bindForm("form-guid").then((form) => {
|
|
366
|
+
// Access elements by their logical name
|
|
367
|
+
const nameField = form["name"];
|
|
368
|
+
|
|
369
|
+
// execute custom methods
|
|
370
|
+
nameField.applyBusinessRule(
|
|
371
|
+
{
|
|
372
|
+
setVisibility: [() => someNode.value === "desired value"],
|
|
373
|
+
},
|
|
374
|
+
[someNode]
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
// Or executes methods immediately upon accessing
|
|
378
|
+
form["phonenumber"].addTooltip("Example tooltip text");
|
|
256
379
|
});
|
|
380
|
+
```
|
|
257
381
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
382
|
+
##### Method Signature
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
/**
|
|
386
|
+
* Binds a form by its GUID and returns a collection of form elements
|
|
387
|
+
* @param formGuid Unique identifier for the form
|
|
388
|
+
* @returns Promise resolving to form element references
|
|
389
|
+
*/
|
|
390
|
+
function bindForm(formGuid: string): Promise<DOMNodeReferenceArray & Record<string: DOMNodeReference>>;
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
##### Benefits
|
|
394
|
+
|
|
395
|
+
- Reduces code complexity
|
|
396
|
+
- Improves readability
|
|
397
|
+
- Provides type-safe access to form elements
|
|
398
|
+
- Supports flexible form interactions
|
|
399
|
+
|
|
400
|
+
##### Best Practices
|
|
401
|
+
|
|
402
|
+
- Use logical names consistently
|
|
403
|
+
- Handle async nature of form binding
|
|
404
|
+
- Leverage TypeScript for enhanced type checking
|
|
405
|
+
|
|
406
|
+
##### Error Handling
|
|
407
|
+
|
|
408
|
+
Ensure proper error handling for form binding:
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
bindForm("form-guid")
|
|
412
|
+
.then((form) => {
|
|
413
|
+
// Form processing
|
|
261
414
|
})
|
|
262
415
|
.catch((error) => {
|
|
263
|
-
console.error("
|
|
416
|
+
console.error("Form binding failed", error);
|
|
264
417
|
});
|
|
265
418
|
```
|
|
266
419
|
|
|
267
|
-
|
|
420
|
+
### DataVerse API
|
|
268
421
|
|
|
269
|
-
|
|
422
|
+
Perform secure API calls to DataVerse from your PowerPages site. This method implements the shell deferred token to send requests with `__RequestVerificationToken`
|
|
270
423
|
|
|
271
|
-
|
|
272
|
-
const tableSetName = "accounts"; // The DataVerse table set name
|
|
273
|
-
const recordID = "your-record-id"; // The GUID of the record to retrieve
|
|
424
|
+
#### Create Records
|
|
274
425
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
426
|
+
```typescript
|
|
427
|
+
await API.createRecord("accounts", {
|
|
428
|
+
name: "Gypsum LLC",
|
|
429
|
+
type: "Vendor",
|
|
430
|
+
})
|
|
431
|
+
.then((recordId) => {
|
|
432
|
+
console.log("Created record:", recordId);
|
|
278
433
|
})
|
|
279
434
|
.catch((error) => {
|
|
280
|
-
console.error("
|
|
435
|
+
console.error("Creation failed:", error);
|
|
281
436
|
});
|
|
282
437
|
```
|
|
283
438
|
|
|
284
|
-
|
|
439
|
+
#### Get Records
|
|
285
440
|
|
|
286
|
-
|
|
441
|
+
```typescript
|
|
442
|
+
// Single record
|
|
443
|
+
const record = await API.getRecord(
|
|
444
|
+
"accounts",
|
|
445
|
+
"record-guid",
|
|
446
|
+
"select=name,accountnumber"
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
// Multiple records
|
|
450
|
+
const records = await API.getMultiple(
|
|
451
|
+
"contacts",
|
|
452
|
+
'$filter=firstname eq "Jane"&$select=firstname,lastname'
|
|
453
|
+
);
|
|
454
|
+
```
|
|
287
455
|
|
|
288
|
-
|
|
289
|
-
const tableSetName = "contacts"; // The DataVerse table set name
|
|
290
|
-
const queryParameters =
|
|
291
|
-
"$filter=firstName eq 'John'&$select=firstName,lastName"; // OData query parameters
|
|
456
|
+
#### Update Record
|
|
292
457
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
458
|
+
```typescript
|
|
459
|
+
await API.updateRecord("contacts", "record-guid", {
|
|
460
|
+
name: "Jane Smith",
|
|
461
|
+
email: "jane@example.com",
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Best Practices
|
|
466
|
+
|
|
467
|
+
1. Always await DOMNodeReference creation:
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
const node = await createRef("#element");
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
2. Include all referenced nodes in dependency arrays:
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
node.configureConditionalRendering(
|
|
477
|
+
() => dependentNode.value === "test",
|
|
478
|
+
[dependentNode] // Required!
|
|
479
|
+
);
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
3. Use TypeScript for better type safety and IntelliSense support.
|
|
483
|
+
|
|
484
|
+
4. Use proper error handling with API operations:
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
/* optionally await */ API.createRecord(/*...*/)
|
|
488
|
+
.then((recordId) => {})
|
|
297
489
|
.catch((error) => {
|
|
298
|
-
|
|
490
|
+
// handle your errors appropriately
|
|
299
491
|
});
|
|
300
492
|
```
|
|
301
493
|
|
|
302
|
-
|
|
494
|
+
## TypeScript Support
|
|
303
495
|
|
|
304
|
-
|
|
496
|
+
The package includes full TypeScript definitions and type safety. Use TypeScript for the best development experience and catch potential errors at compile time.
|
|
305
497
|
|
|
306
|
-
|
|
307
|
-
class YourSchemaClass {
|
|
308
|
-
constructor(tableSetName, data) {
|
|
309
|
-
this.setName = tableSetName;
|
|
310
|
-
this.data = data;
|
|
311
|
-
}
|
|
498
|
+
## Contributing
|
|
312
499
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
500
|
+
Contributions are welcome, feel free to create a pull request with enhancements. Please include an explanation of the changes made. All pull requests will be reviewed by the project owner.
|
|
501
|
+
|
|
502
|
+
## License
|
|
503
|
+
|
|
504
|
+
This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
|
|
505
|
+
|
|
506
|
+
## Funding
|
|
507
|
+
|
|
508
|
+
If you like this project, found it useful, or would like to help support the long-term support of this package, please feel free to contribute via GitHub Sponsors: [Keaton-Brewster](https://github.com/sponsors/Keaton-Brewster)
|