agent-docs 1.3.0 → 1.4.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/.husky/pre-commit +2 -0
- package/PLAN.md +4 -3
- package/README.md +4 -3
- package/docs/A4DWORKFLOWS.md +30 -23
- package/docs/AURACOMPONENTS.md +812 -0
- package/docs/LIGHTNINGBASECOMPONENTS.md +217 -60
- package/docs/LWCHTMLTEMPLATES.md +136 -116
- package/docs/PMD.md +141 -115
- package/docs/XPATH31.md +2 -0
- package/package.json +2 -1
package/docs/LWCHTMLTEMPLATES.md
CHANGED
|
@@ -11,20 +11,23 @@
|
|
|
11
11
|
## Template Structure
|
|
12
12
|
|
|
13
13
|
- **Root element:** `<template>` (renders as `<namespace-component-name>`)
|
|
14
|
-
- **Nested `<template>` tags:** required for directives; only allowed
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
- **Nested `<template>` tags:** required for directives; only allowed
|
|
15
|
+
attributes:
|
|
16
|
+
- `for:each`, `iterator:iteratorname`, `lwc:if`, `lwc:else`, `lwc:elseif`,
|
|
17
|
+
`if:true|false`
|
|
18
|
+
- No other directives or HTML attributes (e.g., no `class` on nested
|
|
19
|
+
`<template>`)
|
|
17
20
|
- **No inline `<style>` or `<script>` tags** — use separate CSS/JS files
|
|
18
21
|
- Follow Lightning Design System patterns and accessibility guidelines
|
|
19
22
|
|
|
20
23
|
## Data Binding & Expressions
|
|
21
24
|
|
|
22
|
-
| Syntax
|
|
23
|
-
|
|
24
|
-
| `{property}`
|
|
25
|
-
| `{data.name}`
|
|
26
|
-
| `{!property}`
|
|
27
|
-
| `{handlerMethod}` | Event handler binding
|
|
25
|
+
| Syntax | Usage |
|
|
26
|
+
| ----------------- | ------------------------------------- |
|
|
27
|
+
| `{property}` | Bind data (no spaces around property) |
|
|
28
|
+
| `{data.name}` | Dot notation supported |
|
|
29
|
+
| `{!property}` | Two-way binding (form inputs) |
|
|
30
|
+
| `{handlerMethod}` | Event handler binding |
|
|
28
31
|
|
|
29
32
|
### Allowed Expression Syntax
|
|
30
33
|
|
|
@@ -40,8 +43,7 @@ The `{expression}` binding syntax **only** supports:
|
|
|
40
43
|
|
|
41
44
|
```html
|
|
42
45
|
<!-- ❌ Logical operators -->
|
|
43
|
-
{isReadOnly || isLoading}
|
|
44
|
-
{isActive && isVisible}
|
|
46
|
+
{isReadOnly || isLoading} {isActive && isVisible}
|
|
45
47
|
|
|
46
48
|
<!-- ❌ Negation operator -->
|
|
47
49
|
{!isDisabled}
|
|
@@ -50,28 +52,22 @@ The `{expression}` binding syntax **only** supports:
|
|
|
50
52
|
{isActive ? 'active' : 'inactive'}
|
|
51
53
|
|
|
52
54
|
<!-- ❌ Arithmetic -->
|
|
53
|
-
{count + 1}
|
|
54
|
-
{price * quantity}
|
|
55
|
+
{count + 1} {price * quantity}
|
|
55
56
|
|
|
56
57
|
<!-- ❌ Array indexing -->
|
|
57
|
-
{items[0].name}
|
|
58
|
-
{person[2].name['John']}
|
|
58
|
+
{items[0].name} {person[2].name['John']}
|
|
59
59
|
|
|
60
60
|
<!-- ❌ Function calls in templates -->
|
|
61
|
-
{formatDate(startDate)}
|
|
62
|
-
{calculateTotal()}
|
|
61
|
+
{formatDate(startDate)} {calculateTotal()}
|
|
63
62
|
|
|
64
63
|
<!-- ❌ String concatenation -->
|
|
65
|
-
{'Hello ' + name}
|
|
66
|
-
{`Item: ${itemName}`}
|
|
64
|
+
{'Hello ' + name} {`Item: ${itemName}`}
|
|
67
65
|
|
|
68
66
|
<!-- ❌ Comparisons -->
|
|
69
|
-
{count > 0}
|
|
70
|
-
{status === 'active'}
|
|
67
|
+
{count > 0} {status === 'active'}
|
|
71
68
|
|
|
72
69
|
<!-- ❌ Nullish coalescing / optional chaining in binding -->
|
|
73
|
-
{user?.name}
|
|
74
|
-
{value ?? 'default'}
|
|
70
|
+
{user?.name} {value ?? 'default'}
|
|
75
71
|
```
|
|
76
72
|
|
|
77
73
|
### ✅ The Solution: Use JavaScript Getters
|
|
@@ -79,75 +75,78 @@ The `{expression}` binding syntax **only** supports:
|
|
|
79
75
|
All computed logic **must** be moved to getters in the JavaScript class:
|
|
80
76
|
|
|
81
77
|
**JavaScript (myComponent.js):**
|
|
78
|
+
|
|
82
79
|
```javascript
|
|
83
80
|
import { LightningElement, api, track } from 'lwc';
|
|
84
81
|
|
|
85
82
|
export default class MyComponent extends LightningElement {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
83
|
+
@api isReadOnly = false;
|
|
84
|
+
@api isLoading = false;
|
|
85
|
+
@track items = [];
|
|
86
|
+
|
|
87
|
+
// ✅ Logical operators → getter
|
|
88
|
+
get isDisabled() {
|
|
89
|
+
return this.isReadOnly || this.isLoading;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ✅ Negation → getter
|
|
93
|
+
get isEnabled() {
|
|
94
|
+
return !this.isDisabled;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ✅ Ternary → getter
|
|
98
|
+
get buttonLabel() {
|
|
99
|
+
return this.isLoading ? 'Loading...' : 'Submit';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ✅ Arithmetic → getter
|
|
103
|
+
get itemCountPlusOne() {
|
|
104
|
+
return this.count + 1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ✅ Array indexing → getter
|
|
108
|
+
get firstItemName() {
|
|
109
|
+
return this.items[0]?.name || '';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ✅ String formatting → getter
|
|
113
|
+
get formattedCount() {
|
|
114
|
+
return `${this.count} items`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ✅ Comparisons for conditional rendering → getter
|
|
118
|
+
get hasItems() {
|
|
119
|
+
return this.items.length > 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ✅ Complex class computation → getter
|
|
123
|
+
get containerClass() {
|
|
124
|
+
return {
|
|
125
|
+
'slds-box': true,
|
|
126
|
+
'slds-theme_shade': this.isActive,
|
|
127
|
+
'slds-hide': !this.isVisible,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
133
130
|
}
|
|
134
131
|
```
|
|
135
132
|
|
|
136
133
|
**HTML (myComponent.html):**
|
|
134
|
+
|
|
137
135
|
```html
|
|
138
136
|
<template>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
137
|
+
<template lwc:if="{hasItems}">
|
|
138
|
+
<div class="{containerClass}">
|
|
139
|
+
<p>{formattedCount}</p>
|
|
140
|
+
<p>First item: {firstItemName}</p>
|
|
141
|
+
</div>
|
|
142
|
+
</template>
|
|
143
|
+
|
|
144
|
+
<lightning-button
|
|
145
|
+
label="{buttonLabel}"
|
|
146
|
+
disabled="{isDisabled}"
|
|
147
|
+
onclick="{handleClick}"
|
|
148
|
+
>
|
|
149
|
+
</lightning-button>
|
|
151
150
|
</template>
|
|
152
151
|
```
|
|
153
152
|
|
|
@@ -155,17 +154,20 @@ export default class MyComponent extends LightningElement {
|
|
|
155
154
|
|
|
156
155
|
Salesforce made this intentional choice for:
|
|
157
156
|
|
|
158
|
-
| Reason
|
|
159
|
-
|
|
160
|
-
| **Performance**
|
|
161
|
-
| **Security**
|
|
162
|
-
| **Predictability** | Reactivity is straightforward—change a property, component re-renders
|
|
163
|
-
| **Testability**
|
|
164
|
-
| **Debugging**
|
|
157
|
+
| Reason | Explanation |
|
|
158
|
+
| ------------------ | -------------------------------------------------------------------------- |
|
|
159
|
+
| **Performance** | Simple property lookups are fast; no runtime expression parsing/evaluation |
|
|
160
|
+
| **Security** | No risk of template injection or expression-based exploits |
|
|
161
|
+
| **Predictability** | Reactivity is straightforward—change a property, component re-renders |
|
|
162
|
+
| **Testability** | All logic lives in unit-testable JavaScript, not scattered in templates |
|
|
163
|
+
| **Debugging** | Stack traces point to JS files, not opaque template expressions |
|
|
165
164
|
|
|
166
165
|
### AI Agent Rule Summary
|
|
167
166
|
|
|
168
|
-
> **LWC Template Expression Rule:** The `{...}` binding syntax accepts ONLY
|
|
167
|
+
> **LWC Template Expression Rule:** The `{...}` binding syntax accepts ONLY
|
|
168
|
+
> property names and dot-notation paths. Any logic requiring operators (`||`,
|
|
169
|
+
> `&&`, `?:`, `+`, `>`, `===`, etc.), function calls, array indexing, or string
|
|
170
|
+
> interpolation MUST be implemented as a getter in the JavaScript class.
|
|
169
171
|
|
|
170
172
|
```
|
|
171
173
|
Template binding: {propertyName} or {object.nested.property}
|
|
@@ -174,41 +176,49 @@ Computed logic: get computedProperty() { return /* any JS expression */; }
|
|
|
174
176
|
|
|
175
177
|
## Conditional Rendering
|
|
176
178
|
|
|
177
|
-
Use `lwc:if`, `lwc:elseif`, `lwc:else` directives (prefer over multiple
|
|
179
|
+
Use `lwc:if`, `lwc:elseif`, `lwc:else` directives (prefer over multiple
|
|
180
|
+
templates for simple conditions):
|
|
178
181
|
|
|
179
182
|
```html
|
|
180
|
-
<template lwc:if={condition}>...</template>
|
|
181
|
-
<template lwc:elseif={otherCondition}>...</template>
|
|
183
|
+
<template lwc:if="{condition}">...</template>
|
|
184
|
+
<template lwc:elseif="{otherCondition}">...</template>
|
|
182
185
|
<template lwc:else>...</template>
|
|
183
186
|
```
|
|
184
187
|
|
|
185
|
-
**Note:** The condition must be a simple property reference or getter—not an
|
|
188
|
+
**Note:** The condition must be a simple property reference or getter—not an
|
|
189
|
+
expression:
|
|
186
190
|
|
|
187
191
|
```html
|
|
188
192
|
<!-- ❌ Invalid -->
|
|
189
|
-
<template lwc:if={items.length
|
|
193
|
+
<template lwc:if="{items.length">
|
|
194
|
+
0}>
|
|
190
195
|
|
|
191
|
-
<!-- ✅ Valid — use a getter -->
|
|
192
|
-
<template lwc:if={hasItems}
|
|
196
|
+
<!-- ✅ Valid — use a getter -->
|
|
197
|
+
<template lwc:if="{hasItems}"></template
|
|
198
|
+
></template>
|
|
193
199
|
```
|
|
194
200
|
|
|
195
201
|
## List Rendering
|
|
196
202
|
|
|
197
203
|
### for:each
|
|
204
|
+
|
|
198
205
|
```html
|
|
199
|
-
<template for:each={array} for:item="item">
|
|
200
|
-
|
|
206
|
+
<template for:each="{array}" for:item="item">
|
|
207
|
+
<div key="{item.uniqueId}">{item.property}</div>
|
|
201
208
|
</template>
|
|
202
209
|
```
|
|
210
|
+
|
|
203
211
|
- `key` required: string/number, **not** index or object
|
|
204
212
|
- Access current item via `for:item="itemName"` → `{itemName.property}`
|
|
205
213
|
|
|
206
214
|
### iterator
|
|
215
|
+
|
|
207
216
|
```html
|
|
208
|
-
<template iterator:it={array}>
|
|
209
|
-
|
|
217
|
+
<template iterator:it="{array}">
|
|
218
|
+
<div key="{it.value.uniqueId}">{it.value.property}</div>
|
|
210
219
|
</template>
|
|
211
220
|
```
|
|
221
|
+
|
|
212
222
|
- Iterator name must be lowercase
|
|
213
223
|
- Properties: `{it.value.property}`, `{it.index}`, `{it.first}`, `{it.last}`
|
|
214
224
|
- Combine with `lwc:if` for first/last styling: `lwc:if={it.first}`
|
|
@@ -219,21 +229,24 @@ Use `lwc:if`, `lwc:elseif`, `lwc:else` directives (prefer over multiple template
|
|
|
219
229
|
- Override `render()` to return template based on state
|
|
220
230
|
- CSS must match template filename: `templateTwo.html` → `templateTwo.css`
|
|
221
231
|
- Default: `componentName.html` when no `render()` override
|
|
222
|
-
- **Prefer `lwc:if` for simple variations; use multiple templates for
|
|
232
|
+
- **Prefer `lwc:if` for simple variations; use multiple templates for
|
|
233
|
+
significantly different layouts**
|
|
223
234
|
|
|
224
235
|
## Class Object Binding (LWC API v62.0+)
|
|
225
236
|
|
|
226
237
|
Bind dynamic classes using arrays or objects instead of string concatenation:
|
|
227
238
|
|
|
228
|
-
| Input
|
|
229
|
-
|
|
230
|
-
| `["highlight", "yellow"]`
|
|
231
|
-
| `{highlight: true, hidden: false}` | `class="highlight"`
|
|
239
|
+
| Input | Output |
|
|
240
|
+
| ---------------------------------- | -------------------------- |
|
|
241
|
+
| `["highlight", "yellow"]` | `class="highlight yellow"` |
|
|
242
|
+
| `{highlight: true, hidden: false}` | `class="highlight"` |
|
|
232
243
|
|
|
233
|
-
- Booleans, numbers, functions render as empty string (use `String(value)` if
|
|
244
|
+
- Booleans, numbers, functions render as empty string (use `String(value)` if
|
|
245
|
+
needed)
|
|
234
246
|
- Use getters to compute complex class combinations
|
|
235
247
|
|
|
236
248
|
**Example with getter:**
|
|
249
|
+
|
|
237
250
|
```javascript
|
|
238
251
|
get cardClasses() {
|
|
239
252
|
return {
|
|
@@ -245,7 +258,7 @@ get cardClasses() {
|
|
|
245
258
|
```
|
|
246
259
|
|
|
247
260
|
```html
|
|
248
|
-
<div class={cardClasses}>...</div>
|
|
261
|
+
<div class="{cardClasses}">...</div>
|
|
249
262
|
```
|
|
250
263
|
|
|
251
264
|
## Inline Style Binding
|
|
@@ -253,9 +266,11 @@ get cardClasses() {
|
|
|
253
266
|
- Syntax: `style={computedStyles}`
|
|
254
267
|
- Getter returns semi-colon separated properties: `width: 50%; font-size: 20px`
|
|
255
268
|
- Use kebab-case CSS properties (`font-size`, not `fontSize`)
|
|
256
|
-
- **Prefer CSS classes over inline styles**; use inline for dynamic/computed
|
|
269
|
+
- **Prefer CSS classes over inline styles**; use inline for dynamic/computed
|
|
270
|
+
values only
|
|
257
271
|
|
|
258
272
|
**Example:**
|
|
273
|
+
|
|
259
274
|
```javascript
|
|
260
275
|
get progressBarStyle() {
|
|
261
276
|
return `width: ${this.progressPercent}%; background-color: ${this.barColor}`;
|
|
@@ -263,7 +278,7 @@ get progressBarStyle() {
|
|
|
263
278
|
```
|
|
264
279
|
|
|
265
280
|
```html
|
|
266
|
-
<div class="progress-bar" style={progressBarStyle}></div>
|
|
281
|
+
<div class="progress-bar" style="{progressBarStyle}"></div>
|
|
267
282
|
```
|
|
268
283
|
|
|
269
284
|
## Event Handling
|
|
@@ -275,10 +290,12 @@ get progressBarStyle() {
|
|
|
275
290
|
|
|
276
291
|
```html
|
|
277
292
|
<!-- ❌ Invalid — no inline functions -->
|
|
278
|
-
<button onclick={()
|
|
293
|
+
<button onclick="{()" ="">
|
|
294
|
+
this.handleClick()}>
|
|
279
295
|
|
|
280
|
-
<!-- ✅ Valid — method reference -->
|
|
281
|
-
<button onclick={handleClick}>
|
|
296
|
+
<!-- ✅ Valid — method reference -->
|
|
297
|
+
<button onclick="{handleClick}"></button>
|
|
298
|
+
</button>
|
|
282
299
|
```
|
|
283
300
|
|
|
284
301
|
## Accessibility
|
|
@@ -292,7 +309,8 @@ get progressBarStyle() {
|
|
|
292
309
|
- Minimize DOM manipulation
|
|
293
310
|
- Use lazy loading / pagination for large lists
|
|
294
311
|
- Avoid unnecessary rerenders by optimizing data binding
|
|
295
|
-
- Getters are re-evaluated on every render—keep them lightweight or cache
|
|
312
|
+
- Getters are re-evaluated on every render—keep them lightweight or cache
|
|
313
|
+
expensive computations
|
|
296
314
|
|
|
297
315
|
## Validation Checklist
|
|
298
316
|
|
|
@@ -303,11 +321,13 @@ get progressBarStyle() {
|
|
|
303
321
|
- [ ] No inline `<style>` or `<script>` tags
|
|
304
322
|
- [ ] No manual DOM manipulation in JS
|
|
305
323
|
- [ ] Data binding: `{property}` syntax, no spaces
|
|
306
|
-
- [ ] **No computed expressions in templates** (no operators, function calls,
|
|
324
|
+
- [ ] **No computed expressions in templates** (no operators, function calls,
|
|
325
|
+
array indexing)
|
|
307
326
|
- [ ] **All computed logic implemented as getters in JS class**
|
|
308
327
|
- [ ] `for:each`: has `for:item` and unique `key` (string/number)
|
|
309
328
|
- [ ] `iterator`: lowercase name, unique `key={it.value.uniqueId}`
|
|
310
|
-
- [ ] Multiple templates: proper imports, `render()` override, matching CSS
|
|
329
|
+
- [ ] Multiple templates: proper imports, `render()` override, matching CSS
|
|
330
|
+
filenames
|
|
311
331
|
- [ ] Class binding follows v62.0+ semantics (arrays/objects via getters)
|
|
312
332
|
- [ ] Inline styles: `style={getter}`, kebab-case properties
|
|
313
333
|
- [ ] Valid HTML syntax (use Salesforce Extensions Pack for validation)
|