@saschabrunnerch/arcgis-maps-sdk-js-ai-context 0.0.1 → 0.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.
- package/README.md +163 -201
- package/bin/cli.js +157 -173
- package/contexts/4.34/{claude → skills}/arcgis-3d-advanced/SKILL.md +586 -586
- package/contexts/4.34/{claude → skills}/arcgis-advanced-layers/SKILL.md +431 -431
- package/contexts/4.34/{claude → skills}/arcgis-analysis-services/SKILL.md +607 -607
- package/contexts/4.34/{claude → skills}/arcgis-authentication/SKILL.md +301 -301
- package/contexts/4.34/{claude → skills}/arcgis-cim-symbols/SKILL.md +486 -486
- package/contexts/4.34/{claude → skills}/arcgis-coordinates-projection/SKILL.md +406 -406
- package/contexts/4.34/{claude → skills}/arcgis-core-maps/SKILL.md +739 -739
- package/contexts/4.34/{claude → skills}/arcgis-core-utilities/SKILL.md +732 -732
- package/contexts/4.34/{claude → skills}/arcgis-custom-rendering/SKILL.md +445 -445
- package/contexts/4.34/{claude → skills}/arcgis-editing-advanced/SKILL.md +702 -702
- package/contexts/4.34/{claude → skills}/arcgis-feature-effects/SKILL.md +393 -393
- package/contexts/4.34/{claude → skills}/arcgis-geometry-operations/SKILL.md +489 -489
- package/contexts/4.34/{claude → skills}/arcgis-imagery/SKILL.md +307 -307
- package/contexts/4.34/{claude → skills}/arcgis-interaction/SKILL.md +572 -572
- package/contexts/4.34/{claude → skills}/arcgis-knowledge-graphs/SKILL.md +582 -582
- package/contexts/4.34/{claude → skills}/arcgis-layers/SKILL.md +601 -601
- package/contexts/4.34/{claude → skills}/arcgis-map-tools/SKILL.md +668 -668
- package/contexts/4.34/{claude → skills}/arcgis-media-layers/SKILL.md +290 -290
- package/contexts/4.34/{claude → skills}/arcgis-portal-content/SKILL.md +679 -679
- package/contexts/4.34/{claude → skills}/arcgis-scene-effects/SKILL.md +512 -512
- package/contexts/4.34/{claude → skills}/arcgis-smart-mapping/SKILL.md +686 -686
- package/contexts/4.34/skills/arcgis-starter-app/SKILL.md +273 -0
- package/contexts/4.34/skills/arcgis-starter-app-extended/SKILL.md +649 -0
- package/contexts/4.34/{claude → skills}/arcgis-tables-forms/SKILL.md +877 -877
- package/contexts/4.34/{claude → skills}/arcgis-time-animation/SKILL.md +722 -722
- package/contexts/4.34/{claude → skills}/arcgis-utility-networks/SKILL.md +301 -301
- package/contexts/4.34/{claude → skills}/arcgis-visualization/SKILL.md +580 -580
- package/contexts/4.34/{claude → skills}/arcgis-widgets-ui/SKILL.md +574 -574
- package/lib/installer.js +294 -379
- package/package.json +45 -45
- package/contexts/4.34/copilot/arcgis-3d.instructions.md +0 -267
- package/contexts/4.34/copilot/arcgis-analysis.instructions.md +0 -294
- package/contexts/4.34/copilot/arcgis-arcade.instructions.md +0 -234
- package/contexts/4.34/copilot/arcgis-authentication.instructions.md +0 -187
- package/contexts/4.34/copilot/arcgis-cim-symbols.instructions.md +0 -177
- package/contexts/4.34/copilot/arcgis-core-maps.instructions.md +0 -246
- package/contexts/4.34/copilot/arcgis-core-utilities.instructions.md +0 -247
- package/contexts/4.34/copilot/arcgis-editing.instructions.md +0 -262
- package/contexts/4.34/copilot/arcgis-geometry.instructions.md +0 -225
- package/contexts/4.34/copilot/arcgis-layers.instructions.md +0 -278
- package/contexts/4.34/copilot/arcgis-popup-templates.instructions.md +0 -266
- package/contexts/4.34/copilot/arcgis-portal-advanced.instructions.md +0 -275
- package/contexts/4.34/copilot/arcgis-smart-mapping.instructions.md +0 -184
- package/contexts/4.34/copilot/arcgis-time-animation.instructions.md +0 -112
- package/contexts/4.34/copilot/arcgis-visualization.instructions.md +0 -321
- package/contexts/4.34/copilot/arcgis-widgets-ui.instructions.md +0 -277
- /package/contexts/4.34/{claude → skills}/arcgis-arcade/SKILL.md +0 -0
- /package/contexts/4.34/{claude → skills}/arcgis-popup-templates/SKILL.md +0 -0
|
@@ -1,877 +1,877 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: arcgis-tables-forms
|
|
3
|
-
description: Configure FeatureTable widget and FormTemplate with input elements. Use for displaying attribute data in tables, customizing edit forms, and configuring field inputs.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ArcGIS Tables & Forms
|
|
7
|
-
|
|
8
|
-
Use this skill for configuring FeatureTable widgets and FormTemplate with various input elements.
|
|
9
|
-
|
|
10
|
-
## FeatureTable
|
|
11
|
-
|
|
12
|
-
Display feature attributes in an interactive table.
|
|
13
|
-
|
|
14
|
-
### FeatureTable Component
|
|
15
|
-
|
|
16
|
-
```html
|
|
17
|
-
<arcgis-map item-id="YOUR_WEBMAP_ID">
|
|
18
|
-
<arcgis-zoom slot="top-left"></arcgis-zoom>
|
|
19
|
-
</arcgis-map>
|
|
20
|
-
|
|
21
|
-
<arcgis-feature-table reference-element="arcgis-map"></arcgis-feature-table>
|
|
22
|
-
|
|
23
|
-
<script type="module">
|
|
24
|
-
const map = document.querySelector("arcgis-map");
|
|
25
|
-
const table = document.querySelector("arcgis-feature-table");
|
|
26
|
-
|
|
27
|
-
await map.viewOnReady();
|
|
28
|
-
|
|
29
|
-
// Set the layer for the table
|
|
30
|
-
const layer = map.view.map.layers.find(l => l.type === "feature");
|
|
31
|
-
table.layer = layer;
|
|
32
|
-
</script>
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### FeatureTable Widget (Core API)
|
|
36
|
-
|
|
37
|
-
```javascript
|
|
38
|
-
import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";
|
|
39
|
-
|
|
40
|
-
const featureTable = new FeatureTable({
|
|
41
|
-
view: view,
|
|
42
|
-
layer: featureLayer,
|
|
43
|
-
container: "tableDiv"
|
|
44
|
-
});
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### With Field Configuration
|
|
48
|
-
|
|
49
|
-
```javascript
|
|
50
|
-
const featureTable = new FeatureTable({
|
|
51
|
-
view: view,
|
|
52
|
-
layer: featureLayer,
|
|
53
|
-
container: "tableDiv",
|
|
54
|
-
fieldConfigs: [
|
|
55
|
-
{
|
|
56
|
-
name: "name",
|
|
57
|
-
label: "Name",
|
|
58
|
-
direction: "asc" // Initial sort
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: "category",
|
|
62
|
-
label: "Category"
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: "value",
|
|
66
|
-
label: "Value",
|
|
67
|
-
format: {
|
|
68
|
-
digitSeparator: true,
|
|
69
|
-
places: 2
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
name: "date_created",
|
|
74
|
-
label: "Created",
|
|
75
|
-
format: {
|
|
76
|
-
dateFormat: "short-date"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### FeatureTable Configuration
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
const featureTable = new FeatureTable({
|
|
87
|
-
view: view,
|
|
88
|
-
layer: featureLayer,
|
|
89
|
-
container: "tableDiv",
|
|
90
|
-
|
|
91
|
-
// Display options
|
|
92
|
-
visibleElements: {
|
|
93
|
-
header: true,
|
|
94
|
-
menu: true,
|
|
95
|
-
menuItems: {
|
|
96
|
-
clearSelection: true,
|
|
97
|
-
refreshData: true,
|
|
98
|
-
toggleColumns: true,
|
|
99
|
-
selectedRecordsShowAllToggle: true,
|
|
100
|
-
selectedRecordsShowSelectedToggle: true,
|
|
101
|
-
zoomToSelection: true
|
|
102
|
-
},
|
|
103
|
-
selectionColumn: true,
|
|
104
|
-
columnMenus: true
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
// Table behavior
|
|
108
|
-
multiSortEnabled: true,
|
|
109
|
-
editingEnabled: true,
|
|
110
|
-
highlightEnabled: true,
|
|
111
|
-
attachmentsEnabled: true,
|
|
112
|
-
relatedRecordsEnabled: true,
|
|
113
|
-
|
|
114
|
-
// Pagination
|
|
115
|
-
pageSize: 50,
|
|
116
|
-
|
|
117
|
-
// Initial state
|
|
118
|
-
filterGeometry: view.extent, // Only show features in view
|
|
119
|
-
highlightOnRowSelectEnabled: true
|
|
120
|
-
});
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Column Templates
|
|
124
|
-
|
|
125
|
-
```javascript
|
|
126
|
-
import FieldColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/FieldColumnTemplate.js";
|
|
127
|
-
|
|
128
|
-
const featureTable = new FeatureTable({
|
|
129
|
-
view: view,
|
|
130
|
-
layer: featureLayer,
|
|
131
|
-
tableTemplate: {
|
|
132
|
-
columnTemplates: [
|
|
133
|
-
new FieldColumnTemplate({
|
|
134
|
-
fieldName: "name",
|
|
135
|
-
label: "Name",
|
|
136
|
-
sortable: true,
|
|
137
|
-
initialSortPriority: 0,
|
|
138
|
-
direction: "asc"
|
|
139
|
-
}),
|
|
140
|
-
new FieldColumnTemplate({
|
|
141
|
-
fieldName: "status",
|
|
142
|
-
label: "Status",
|
|
143
|
-
menuConfig: {
|
|
144
|
-
items: [{
|
|
145
|
-
label: "Custom Action",
|
|
146
|
-
iconClass: "esri-icon-settings",
|
|
147
|
-
clickFunction: (event) => {
|
|
148
|
-
console.log("Custom action on:", event.feature);
|
|
149
|
-
}
|
|
150
|
-
}]
|
|
151
|
-
}
|
|
152
|
-
}),
|
|
153
|
-
new FieldColumnTemplate({
|
|
154
|
-
fieldName: "value",
|
|
155
|
-
label: "Value ($)",
|
|
156
|
-
textAlign: "right",
|
|
157
|
-
formatFunction: (info) => {
|
|
158
|
-
return `$${info.value.toLocaleString()}`;
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
]
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Group Column Template
|
|
167
|
-
|
|
168
|
-
```javascript
|
|
169
|
-
import GroupColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/GroupColumnTemplate.js";
|
|
170
|
-
|
|
171
|
-
const featureTable = new FeatureTable({
|
|
172
|
-
view: view,
|
|
173
|
-
layer: featureLayer,
|
|
174
|
-
tableTemplate: {
|
|
175
|
-
columnTemplates: [
|
|
176
|
-
new GroupColumnTemplate({
|
|
177
|
-
label: "Location",
|
|
178
|
-
columnTemplates: [
|
|
179
|
-
new FieldColumnTemplate({ fieldName: "city", label: "City" }),
|
|
180
|
-
new FieldColumnTemplate({ fieldName: "state", label: "State" }),
|
|
181
|
-
new FieldColumnTemplate({ fieldName: "country", label: "Country" })
|
|
182
|
-
]
|
|
183
|
-
}),
|
|
184
|
-
new GroupColumnTemplate({
|
|
185
|
-
label: "Details",
|
|
186
|
-
columnTemplates: [
|
|
187
|
-
new FieldColumnTemplate({ fieldName: "name", label: "Name" }),
|
|
188
|
-
new FieldColumnTemplate({ fieldName: "type", label: "Type" })
|
|
189
|
-
]
|
|
190
|
-
})
|
|
191
|
-
]
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### FeatureTable Events
|
|
197
|
-
|
|
198
|
-
```javascript
|
|
199
|
-
// Row selection
|
|
200
|
-
featureTable.on("selection-change", (event) => {
|
|
201
|
-
console.log("Added:", event.added);
|
|
202
|
-
console.log("Removed:", event.removed);
|
|
203
|
-
|
|
204
|
-
// Get all selected features
|
|
205
|
-
const selectedFeatures = featureTable.highlightIds.toArray();
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
// Row click (double-click to zoom)
|
|
209
|
-
featureTable.viewModel.on("row-highlight-change", (event) => {
|
|
210
|
-
if (event.feature) {
|
|
211
|
-
view.goTo(event.feature.geometry);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// Editing complete
|
|
216
|
-
featureTable.on("edit-complete", (event) => {
|
|
217
|
-
console.log("Edited feature:", event.feature);
|
|
218
|
-
console.log("Updated attributes:", event.attributes);
|
|
219
|
-
});
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Programmatic Selection
|
|
223
|
-
|
|
224
|
-
```javascript
|
|
225
|
-
// Select by ObjectIDs
|
|
226
|
-
featureTable.highlightIds.add(123);
|
|
227
|
-
featureTable.highlightIds.addMany([124, 125, 126]);
|
|
228
|
-
|
|
229
|
-
// Clear selection
|
|
230
|
-
featureTable.highlightIds.removeAll();
|
|
231
|
-
|
|
232
|
-
// Select from query
|
|
233
|
-
const results = await featureLayer.queryObjectIds({
|
|
234
|
-
where: "status = 'active'"
|
|
235
|
-
});
|
|
236
|
-
featureTable.highlightIds.addMany(results);
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Filter and Refresh
|
|
240
|
-
|
|
241
|
-
```javascript
|
|
242
|
-
// Filter by geometry
|
|
243
|
-
featureTable.filterGeometry = view.extent;
|
|
244
|
-
|
|
245
|
-
// Filter by expression
|
|
246
|
-
featureTable.layer.definitionExpression = "category = 'A'";
|
|
247
|
-
|
|
248
|
-
// Refresh data
|
|
249
|
-
featureTable.refresh();
|
|
250
|
-
|
|
251
|
-
// Clear filters
|
|
252
|
-
featureTable.filterGeometry = null;
|
|
253
|
-
featureTable.layer.definitionExpression = null;
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Sync with Map Selection
|
|
257
|
-
|
|
258
|
-
```javascript
|
|
259
|
-
// Map click selects in table
|
|
260
|
-
view.on("click", async (event) => {
|
|
261
|
-
const response = await view.hitTest(event);
|
|
262
|
-
const feature = response.results.find(r => r.layer === featureLayer);
|
|
263
|
-
|
|
264
|
-
if (feature) {
|
|
265
|
-
featureTable.highlightIds.removeAll();
|
|
266
|
-
featureTable.highlightIds.add(feature.graphic.attributes.OBJECTID);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
// Table selection highlights on map
|
|
271
|
-
featureTable.on("selection-change", async (event) => {
|
|
272
|
-
const layerView = await view.whenLayerView(featureLayer);
|
|
273
|
-
|
|
274
|
-
if (highlightHandle) {
|
|
275
|
-
highlightHandle.remove();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const objectIds = featureTable.highlightIds.toArray();
|
|
279
|
-
if (objectIds.length > 0) {
|
|
280
|
-
const query = featureLayer.createQuery();
|
|
281
|
-
query.objectIds = objectIds;
|
|
282
|
-
const results = await featureLayer.queryFeatures(query);
|
|
283
|
-
highlightHandle = layerView.highlight(results.features);
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## FormTemplate
|
|
289
|
-
|
|
290
|
-
Configure edit forms for features.
|
|
291
|
-
|
|
292
|
-
### Basic FormTemplate
|
|
293
|
-
|
|
294
|
-
```javascript
|
|
295
|
-
import FormTemplate from "@arcgis/core/form/FormTemplate.js";
|
|
296
|
-
|
|
297
|
-
const formTemplate = new FormTemplate({
|
|
298
|
-
title: "Edit Feature",
|
|
299
|
-
description: "Update the feature attributes",
|
|
300
|
-
elements: [
|
|
301
|
-
{
|
|
302
|
-
type: "field",
|
|
303
|
-
fieldName: "name",
|
|
304
|
-
label: "Name"
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
type: "field",
|
|
308
|
-
fieldName: "category",
|
|
309
|
-
label: "Category"
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
type: "field",
|
|
313
|
-
fieldName: "description",
|
|
314
|
-
label: "Description"
|
|
315
|
-
}
|
|
316
|
-
]
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
featureLayer.formTemplate = formTemplate;
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### Field Elements
|
|
323
|
-
|
|
324
|
-
```javascript
|
|
325
|
-
import FieldElement from "@arcgis/core/form/elements/FieldElement.js";
|
|
326
|
-
|
|
327
|
-
const fieldElement = new FieldElement({
|
|
328
|
-
fieldName: "name",
|
|
329
|
-
label: "Name",
|
|
330
|
-
description: "Enter the feature name",
|
|
331
|
-
hint: "Required field",
|
|
332
|
-
requiredExpression: "true",
|
|
333
|
-
editableExpression: "$feature.status != 'locked'",
|
|
334
|
-
visibilityExpression: "$feature.type != 'hidden'"
|
|
335
|
-
});
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Group Elements
|
|
339
|
-
|
|
340
|
-
```javascript
|
|
341
|
-
import GroupElement from "@arcgis/core/form/elements/GroupElement.js";
|
|
342
|
-
|
|
343
|
-
const formTemplate = new FormTemplate({
|
|
344
|
-
elements: [
|
|
345
|
-
new GroupElement({
|
|
346
|
-
label: "Basic Information",
|
|
347
|
-
description: "Enter basic details",
|
|
348
|
-
elements: [
|
|
349
|
-
{ type: "field", fieldName: "name", label: "Name" },
|
|
350
|
-
{ type: "field", fieldName: "type", label: "Type" }
|
|
351
|
-
]
|
|
352
|
-
}),
|
|
353
|
-
new GroupElement({
|
|
354
|
-
label: "Location",
|
|
355
|
-
initialState: "collapsed", // expanded, collapsed
|
|
356
|
-
elements: [
|
|
357
|
-
{ type: "field", fieldName: "address", label: "Address" },
|
|
358
|
-
{ type: "field", fieldName: "city", label: "City" },
|
|
359
|
-
{ type: "field", fieldName: "state", label: "State" }
|
|
360
|
-
]
|
|
361
|
-
})
|
|
362
|
-
]
|
|
363
|
-
});
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### Text Elements
|
|
367
|
-
|
|
368
|
-
```javascript
|
|
369
|
-
import TextElement from "@arcgis/core/form/elements/TextElement.js";
|
|
370
|
-
|
|
371
|
-
const formTemplate = new FormTemplate({
|
|
372
|
-
elements: [
|
|
373
|
-
new TextElement({
|
|
374
|
-
type: "text",
|
|
375
|
-
text: "<h3>Important Instructions</h3><p>Please fill out all required fields.</p>"
|
|
376
|
-
}),
|
|
377
|
-
{ type: "field", fieldName: "name", label: "Name" },
|
|
378
|
-
new TextElement({
|
|
379
|
-
text: "<hr><small>Fields below are optional</small>"
|
|
380
|
-
}),
|
|
381
|
-
{ type: "field", fieldName: "notes", label: "Notes" }
|
|
382
|
-
]
|
|
383
|
-
});
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
### Relationship Elements
|
|
387
|
-
|
|
388
|
-
```javascript
|
|
389
|
-
import RelationshipElement from "@arcgis/core/form/elements/RelationshipElement.js";
|
|
390
|
-
|
|
391
|
-
const formTemplate = new FormTemplate({
|
|
392
|
-
elements: [
|
|
393
|
-
{ type: "field", fieldName: "name", label: "Name" },
|
|
394
|
-
new RelationshipElement({
|
|
395
|
-
relationshipId: 0,
|
|
396
|
-
label: "Related Inspections",
|
|
397
|
-
description: "View and manage related inspection records",
|
|
398
|
-
displayCount: 5,
|
|
399
|
-
orderByFields: [{
|
|
400
|
-
field: "inspection_date",
|
|
401
|
-
order: "desc"
|
|
402
|
-
}],
|
|
403
|
-
editableExpression: "true"
|
|
404
|
-
})
|
|
405
|
-
]
|
|
406
|
-
});
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
## Input Types
|
|
410
|
-
|
|
411
|
-
### TextBox Input
|
|
412
|
-
|
|
413
|
-
```javascript
|
|
414
|
-
{
|
|
415
|
-
type: "field",
|
|
416
|
-
fieldName: "name",
|
|
417
|
-
label: "Name",
|
|
418
|
-
input: {
|
|
419
|
-
type: "text-box",
|
|
420
|
-
maxLength: 100,
|
|
421
|
-
minLength: 1
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
### TextArea Input
|
|
427
|
-
|
|
428
|
-
```javascript
|
|
429
|
-
{
|
|
430
|
-
type: "field",
|
|
431
|
-
fieldName: "description",
|
|
432
|
-
label: "Description",
|
|
433
|
-
input: {
|
|
434
|
-
type: "text-area",
|
|
435
|
-
maxLength: 1000,
|
|
436
|
-
minLength: 0
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### ComboBox Input
|
|
442
|
-
|
|
443
|
-
```javascript
|
|
444
|
-
{
|
|
445
|
-
type: "field",
|
|
446
|
-
fieldName: "category",
|
|
447
|
-
label: "Category",
|
|
448
|
-
input: {
|
|
449
|
-
type: "combo-box",
|
|
450
|
-
showNoValueOption: true,
|
|
451
|
-
noValueOptionLabel: "Select a category..."
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// Works with coded value domains
|
|
456
|
-
// Domain values automatically populate the combo box
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### Radio Buttons Input
|
|
460
|
-
|
|
461
|
-
```javascript
|
|
462
|
-
{
|
|
463
|
-
type: "field",
|
|
464
|
-
fieldName: "priority",
|
|
465
|
-
label: "Priority",
|
|
466
|
-
input: {
|
|
467
|
-
type: "radio-buttons",
|
|
468
|
-
showNoValueOption: false
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
### Switch Input
|
|
474
|
-
|
|
475
|
-
```javascript
|
|
476
|
-
{
|
|
477
|
-
type: "field",
|
|
478
|
-
fieldName: "is_active",
|
|
479
|
-
label: "Active",
|
|
480
|
-
input: {
|
|
481
|
-
type: "switch",
|
|
482
|
-
offValue: 0,
|
|
483
|
-
onValue: 1
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### DatePicker Input
|
|
489
|
-
|
|
490
|
-
```javascript
|
|
491
|
-
{
|
|
492
|
-
type: "field",
|
|
493
|
-
fieldName: "start_date",
|
|
494
|
-
label: "Start Date",
|
|
495
|
-
input: {
|
|
496
|
-
type: "date-picker",
|
|
497
|
-
min: new Date("2020-01-01"),
|
|
498
|
-
max: new Date("2030-12-31"),
|
|
499
|
-
includeTime: false
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
### DateTimePicker Input
|
|
505
|
-
|
|
506
|
-
```javascript
|
|
507
|
-
{
|
|
508
|
-
type: "field",
|
|
509
|
-
fieldName: "event_datetime",
|
|
510
|
-
label: "Event Date/Time",
|
|
511
|
-
input: {
|
|
512
|
-
type: "datetime-picker",
|
|
513
|
-
min: new Date("2020-01-01T00:00:00"),
|
|
514
|
-
max: new Date("2030-12-31T23:59:59"),
|
|
515
|
-
includeTime: true
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
### TimePicker Input
|
|
521
|
-
|
|
522
|
-
```javascript
|
|
523
|
-
{
|
|
524
|
-
type: "field",
|
|
525
|
-
fieldName: "event_time",
|
|
526
|
-
label: "Event Time",
|
|
527
|
-
input: {
|
|
528
|
-
type: "time-picker"
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
### Barcode Scanner Input
|
|
534
|
-
|
|
535
|
-
```javascript
|
|
536
|
-
{
|
|
537
|
-
type: "field",
|
|
538
|
-
fieldName: "barcode",
|
|
539
|
-
label: "Barcode",
|
|
540
|
-
input: {
|
|
541
|
-
type: "barcode-scanner"
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
## Expression-Based Configuration
|
|
547
|
-
|
|
548
|
-
### Visibility Expressions
|
|
549
|
-
|
|
550
|
-
```javascript
|
|
551
|
-
const formTemplate = new FormTemplate({
|
|
552
|
-
expressionInfos: [
|
|
553
|
-
{
|
|
554
|
-
name: "show-commercial-fields",
|
|
555
|
-
expression: "$feature.property_type == 'commercial'"
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
name: "show-residential-fields",
|
|
559
|
-
expression: "$feature.property_type == 'residential'"
|
|
560
|
-
}
|
|
561
|
-
],
|
|
562
|
-
elements: [
|
|
563
|
-
{ type: "field", fieldName: "property_type", label: "Property Type" },
|
|
564
|
-
{
|
|
565
|
-
type: "group",
|
|
566
|
-
label: "Commercial Details",
|
|
567
|
-
visibilityExpression: "show-commercial-fields",
|
|
568
|
-
elements: [
|
|
569
|
-
{ type: "field", fieldName: "business_name", label: "Business Name" },
|
|
570
|
-
{ type: "field", fieldName: "num_employees", label: "Employees" }
|
|
571
|
-
]
|
|
572
|
-
},
|
|
573
|
-
{
|
|
574
|
-
type: "group",
|
|
575
|
-
label: "Residential Details",
|
|
576
|
-
visibilityExpression: "show-residential-fields",
|
|
577
|
-
elements: [
|
|
578
|
-
{ type: "field", fieldName: "num_bedrooms", label: "Bedrooms" },
|
|
579
|
-
{ type: "field", fieldName: "num_bathrooms", label: "Bathrooms" }
|
|
580
|
-
]
|
|
581
|
-
}
|
|
582
|
-
]
|
|
583
|
-
});
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
### Required Expressions
|
|
587
|
-
|
|
588
|
-
```javascript
|
|
589
|
-
{
|
|
590
|
-
type: "field",
|
|
591
|
-
fieldName: "inspection_notes",
|
|
592
|
-
label: "Inspection Notes",
|
|
593
|
-
requiredExpression: "$feature.inspection_result == 'failed'"
|
|
594
|
-
}
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### Editable Expressions
|
|
598
|
-
|
|
599
|
-
```javascript
|
|
600
|
-
{
|
|
601
|
-
type: "field",
|
|
602
|
-
fieldName: "approved_by",
|
|
603
|
-
label: "Approved By",
|
|
604
|
-
editableExpression: "$feature.status == 'pending'"
|
|
605
|
-
}
|
|
606
|
-
```
|
|
607
|
-
|
|
608
|
-
## FeatureForm Widget
|
|
609
|
-
|
|
610
|
-
Widget for editing feature attributes.
|
|
611
|
-
|
|
612
|
-
```javascript
|
|
613
|
-
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
|
|
614
|
-
|
|
615
|
-
const featureForm = new FeatureForm({
|
|
616
|
-
container: "formDiv",
|
|
617
|
-
layer: featureLayer,
|
|
618
|
-
formTemplate: formTemplate
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
// Set feature to edit
|
|
622
|
-
featureForm.feature = selectedGraphic;
|
|
623
|
-
|
|
624
|
-
// Listen for submit
|
|
625
|
-
featureForm.on("submit", () => {
|
|
626
|
-
if (featureForm.feature) {
|
|
627
|
-
const updated = featureForm.getValues();
|
|
628
|
-
|
|
629
|
-
featureLayer.applyEdits({
|
|
630
|
-
updateFeatures: [{
|
|
631
|
-
attributes: {
|
|
632
|
-
...featureForm.feature.attributes,
|
|
633
|
-
...updated
|
|
634
|
-
},
|
|
635
|
-
geometry: featureForm.feature.geometry
|
|
636
|
-
}]
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
});
|
|
640
|
-
|
|
641
|
-
// Handle value changes
|
|
642
|
-
featureForm.on("value-change", (event) => {
|
|
643
|
-
console.log(`${event.fieldName} changed to ${event.value}`);
|
|
644
|
-
});
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
## AttributeTableTemplate
|
|
648
|
-
|
|
649
|
-
Configure attribute table in Editor widget.
|
|
650
|
-
|
|
651
|
-
```javascript
|
|
652
|
-
import AttributeTableTemplate from "@arcgis/core/widgets/Editor/support/AttributeTableTemplate.js";
|
|
653
|
-
import AttributeTableFieldElement from "@arcgis/core/widgets/Editor/support/AttributeTableFieldElement.js";
|
|
654
|
-
|
|
655
|
-
const tableTemplate = new AttributeTableTemplate({
|
|
656
|
-
elements: [
|
|
657
|
-
new AttributeTableFieldElement({
|
|
658
|
-
fieldName: "name",
|
|
659
|
-
label: "Name",
|
|
660
|
-
editable: true
|
|
661
|
-
}),
|
|
662
|
-
new AttributeTableFieldElement({
|
|
663
|
-
fieldName: "status",
|
|
664
|
-
label: "Status",
|
|
665
|
-
editable: true
|
|
666
|
-
})
|
|
667
|
-
]
|
|
668
|
-
});
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
## Editor Widget Integration
|
|
672
|
-
|
|
673
|
-
```javascript
|
|
674
|
-
import Editor from "@arcgis/core/widgets/Editor.js";
|
|
675
|
-
|
|
676
|
-
const editor = new Editor({
|
|
677
|
-
view: view,
|
|
678
|
-
layerInfos: [{
|
|
679
|
-
layer: featureLayer,
|
|
680
|
-
formTemplate: formTemplate,
|
|
681
|
-
enabled: true,
|
|
682
|
-
addEnabled: true,
|
|
683
|
-
updateEnabled: true,
|
|
684
|
-
deleteEnabled: true
|
|
685
|
-
}]
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
view.ui.add(editor, "top-right");
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
## Common Patterns
|
|
692
|
-
|
|
693
|
-
### Complete Form Setup
|
|
694
|
-
|
|
695
|
-
```javascript
|
|
696
|
-
const formTemplate = new FormTemplate({
|
|
697
|
-
title: "Property Information",
|
|
698
|
-
description: "Enter property details",
|
|
699
|
-
preserveFieldValuesWhenHidden: true,
|
|
700
|
-
expressionInfos: [
|
|
701
|
-
{
|
|
702
|
-
name: "is-commercial",
|
|
703
|
-
expression: "$feature.type == 'commercial'"
|
|
704
|
-
}
|
|
705
|
-
],
|
|
706
|
-
elements: [
|
|
707
|
-
// Header text
|
|
708
|
-
{
|
|
709
|
-
type: "text",
|
|
710
|
-
text: "<b>Basic Information</b>"
|
|
711
|
-
},
|
|
712
|
-
// Required field
|
|
713
|
-
{
|
|
714
|
-
type: "field",
|
|
715
|
-
fieldName: "name",
|
|
716
|
-
label: "Property Name",
|
|
717
|
-
requiredExpression: "true",
|
|
718
|
-
input: { type: "text-box", maxLength: 100 }
|
|
719
|
-
},
|
|
720
|
-
// Dropdown
|
|
721
|
-
{
|
|
722
|
-
type: "field",
|
|
723
|
-
fieldName: "type",
|
|
724
|
-
label: "Property Type",
|
|
725
|
-
input: { type: "combo-box" }
|
|
726
|
-
},
|
|
727
|
-
// Conditional group
|
|
728
|
-
{
|
|
729
|
-
type: "group",
|
|
730
|
-
label: "Commercial Details",
|
|
731
|
-
visibilityExpression: "is-commercial",
|
|
732
|
-
elements: [
|
|
733
|
-
{ type: "field", fieldName: "business_type", label: "Business Type" },
|
|
734
|
-
{ type: "field", fieldName: "sqft", label: "Square Footage" }
|
|
735
|
-
]
|
|
736
|
-
},
|
|
737
|
-
// Date field
|
|
738
|
-
{
|
|
739
|
-
type: "field",
|
|
740
|
-
fieldName: "inspection_date",
|
|
741
|
-
label: "Last Inspection",
|
|
742
|
-
input: { type: "date-picker" }
|
|
743
|
-
},
|
|
744
|
-
// Long text
|
|
745
|
-
{
|
|
746
|
-
type: "field",
|
|
747
|
-
fieldName: "notes",
|
|
748
|
-
label: "Notes",
|
|
749
|
-
input: { type: "text-area", maxLength: 500 }
|
|
750
|
-
}
|
|
751
|
-
]
|
|
752
|
-
});
|
|
753
|
-
```
|
|
754
|
-
|
|
755
|
-
### FeatureTable with Editing
|
|
756
|
-
|
|
757
|
-
```javascript
|
|
758
|
-
const featureTable = new FeatureTable({
|
|
759
|
-
view: view,
|
|
760
|
-
layer: featureLayer,
|
|
761
|
-
container: "tableDiv",
|
|
762
|
-
editingEnabled: true,
|
|
763
|
-
fieldConfigs: [
|
|
764
|
-
{ name: "name", label: "Name", editable: true },
|
|
765
|
-
{ name: "status", label: "Status", editable: true },
|
|
766
|
-
{ name: "created_date", label: "Created", editable: false }
|
|
767
|
-
]
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
featureTable.on("edit-complete", async (event) => {
|
|
771
|
-
console.log("Edit saved:", event.feature.attributes);
|
|
772
|
-
|
|
773
|
-
// Refresh related data
|
|
774
|
-
await featureLayer.refresh();
|
|
775
|
-
});
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
### Responsive Table Layout
|
|
779
|
-
|
|
780
|
-
```javascript
|
|
781
|
-
const featureTable = new FeatureTable({
|
|
782
|
-
view: view,
|
|
783
|
-
layer: featureLayer,
|
|
784
|
-
container: "tableDiv",
|
|
785
|
-
autoRefreshEnabled: true,
|
|
786
|
-
pageSize: 25
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
// Resize handling
|
|
790
|
-
window.addEventListener("resize", () => {
|
|
791
|
-
featureTable.refresh();
|
|
792
|
-
});
|
|
793
|
-
|
|
794
|
-
// Toggle visibility
|
|
795
|
-
function toggleTable(visible) {
|
|
796
|
-
document.getElementById("tableDiv").style.display = visible ? "block" : "none";
|
|
797
|
-
if (visible) {
|
|
798
|
-
featureTable.refresh();
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
```
|
|
802
|
-
|
|
803
|
-
## TypeScript Usage
|
|
804
|
-
|
|
805
|
-
Form elements use autocasting with `type` properties. For TypeScript safety, use `as const`:
|
|
806
|
-
|
|
807
|
-
```typescript
|
|
808
|
-
// Use 'as const' for type safety in form templates
|
|
809
|
-
const formTemplate = {
|
|
810
|
-
title: "Edit Feature",
|
|
811
|
-
elements: [
|
|
812
|
-
{
|
|
813
|
-
type: "field",
|
|
814
|
-
fieldName: "name",
|
|
815
|
-
label: "Name"
|
|
816
|
-
},
|
|
817
|
-
{
|
|
818
|
-
type: "group",
|
|
819
|
-
label: "Address",
|
|
820
|
-
elements: [
|
|
821
|
-
{ type: "field", fieldName: "street" },
|
|
822
|
-
{ type: "field", fieldName: "city" }
|
|
823
|
-
]
|
|
824
|
-
}
|
|
825
|
-
]
|
|
826
|
-
} as const;
|
|
827
|
-
|
|
828
|
-
// For input types
|
|
829
|
-
const formElement = {
|
|
830
|
-
type: "field",
|
|
831
|
-
fieldName: "status",
|
|
832
|
-
input: { type: "combo-box" }
|
|
833
|
-
} as const;
|
|
834
|
-
```
|
|
835
|
-
|
|
836
|
-
> **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
|
|
837
|
-
|
|
838
|
-
## Common Pitfalls
|
|
839
|
-
|
|
840
|
-
1. **Field Names Must Match**: fieldName must exactly match layer field
|
|
841
|
-
```javascript
|
|
842
|
-
// Layer has field "PropertyName"
|
|
843
|
-
{ fieldName: "PropertyName" } // Correct
|
|
844
|
-
{ fieldName: "propertyname" } // Wrong - case sensitive
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
2. **Coded Value Domains**: ComboBox auto-populates from domain
|
|
848
|
-
```javascript
|
|
849
|
-
// If field has coded value domain, values come from domain
|
|
850
|
-
{ type: "field", fieldName: "status", input: { type: "combo-box" } }
|
|
851
|
-
// Dropdown shows domain values automatically
|
|
852
|
-
```
|
|
853
|
-
|
|
854
|
-
3. **Expression Names**: Reference expressions by name string
|
|
855
|
-
```javascript
|
|
856
|
-
expressionInfos: [{ name: "my-expr", expression: "..." }],
|
|
857
|
-
elements: [{
|
|
858
|
-
visibilityExpression: "my-expr" // String reference
|
|
859
|
-
}]
|
|
860
|
-
```
|
|
861
|
-
|
|
862
|
-
4. **Layer Must Be Editable**: For edit features to work
|
|
863
|
-
```javascript
|
|
864
|
-
// Layer capabilities must include editing
|
|
865
|
-
if (layer.capabilities.editing.supportsUpdateByOthers) {
|
|
866
|
-
featureTable.editingEnabled = true;
|
|
867
|
-
}
|
|
868
|
-
```
|
|
869
|
-
|
|
870
|
-
5. **Container Size**: Table needs explicit height
|
|
871
|
-
```css
|
|
872
|
-
#tableDiv {
|
|
873
|
-
height: 400px; /* Required */
|
|
874
|
-
width: 100%;
|
|
875
|
-
}
|
|
876
|
-
```
|
|
877
|
-
|
|
1
|
+
---
|
|
2
|
+
name: arcgis-tables-forms
|
|
3
|
+
description: Configure FeatureTable widget and FormTemplate with input elements. Use for displaying attribute data in tables, customizing edit forms, and configuring field inputs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ArcGIS Tables & Forms
|
|
7
|
+
|
|
8
|
+
Use this skill for configuring FeatureTable widgets and FormTemplate with various input elements.
|
|
9
|
+
|
|
10
|
+
## FeatureTable
|
|
11
|
+
|
|
12
|
+
Display feature attributes in an interactive table.
|
|
13
|
+
|
|
14
|
+
### FeatureTable Component
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<arcgis-map item-id="YOUR_WEBMAP_ID">
|
|
18
|
+
<arcgis-zoom slot="top-left"></arcgis-zoom>
|
|
19
|
+
</arcgis-map>
|
|
20
|
+
|
|
21
|
+
<arcgis-feature-table reference-element="arcgis-map"></arcgis-feature-table>
|
|
22
|
+
|
|
23
|
+
<script type="module">
|
|
24
|
+
const map = document.querySelector("arcgis-map");
|
|
25
|
+
const table = document.querySelector("arcgis-feature-table");
|
|
26
|
+
|
|
27
|
+
await map.viewOnReady();
|
|
28
|
+
|
|
29
|
+
// Set the layer for the table
|
|
30
|
+
const layer = map.view.map.layers.find(l => l.type === "feature");
|
|
31
|
+
table.layer = layer;
|
|
32
|
+
</script>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### FeatureTable Widget (Core API)
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";
|
|
39
|
+
|
|
40
|
+
const featureTable = new FeatureTable({
|
|
41
|
+
view: view,
|
|
42
|
+
layer: featureLayer,
|
|
43
|
+
container: "tableDiv"
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With Field Configuration
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const featureTable = new FeatureTable({
|
|
51
|
+
view: view,
|
|
52
|
+
layer: featureLayer,
|
|
53
|
+
container: "tableDiv",
|
|
54
|
+
fieldConfigs: [
|
|
55
|
+
{
|
|
56
|
+
name: "name",
|
|
57
|
+
label: "Name",
|
|
58
|
+
direction: "asc" // Initial sort
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "category",
|
|
62
|
+
label: "Category"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "value",
|
|
66
|
+
label: "Value",
|
|
67
|
+
format: {
|
|
68
|
+
digitSeparator: true,
|
|
69
|
+
places: 2
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "date_created",
|
|
74
|
+
label: "Created",
|
|
75
|
+
format: {
|
|
76
|
+
dateFormat: "short-date"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### FeatureTable Configuration
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const featureTable = new FeatureTable({
|
|
87
|
+
view: view,
|
|
88
|
+
layer: featureLayer,
|
|
89
|
+
container: "tableDiv",
|
|
90
|
+
|
|
91
|
+
// Display options
|
|
92
|
+
visibleElements: {
|
|
93
|
+
header: true,
|
|
94
|
+
menu: true,
|
|
95
|
+
menuItems: {
|
|
96
|
+
clearSelection: true,
|
|
97
|
+
refreshData: true,
|
|
98
|
+
toggleColumns: true,
|
|
99
|
+
selectedRecordsShowAllToggle: true,
|
|
100
|
+
selectedRecordsShowSelectedToggle: true,
|
|
101
|
+
zoomToSelection: true
|
|
102
|
+
},
|
|
103
|
+
selectionColumn: true,
|
|
104
|
+
columnMenus: true
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// Table behavior
|
|
108
|
+
multiSortEnabled: true,
|
|
109
|
+
editingEnabled: true,
|
|
110
|
+
highlightEnabled: true,
|
|
111
|
+
attachmentsEnabled: true,
|
|
112
|
+
relatedRecordsEnabled: true,
|
|
113
|
+
|
|
114
|
+
// Pagination
|
|
115
|
+
pageSize: 50,
|
|
116
|
+
|
|
117
|
+
// Initial state
|
|
118
|
+
filterGeometry: view.extent, // Only show features in view
|
|
119
|
+
highlightOnRowSelectEnabled: true
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Column Templates
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import FieldColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/FieldColumnTemplate.js";
|
|
127
|
+
|
|
128
|
+
const featureTable = new FeatureTable({
|
|
129
|
+
view: view,
|
|
130
|
+
layer: featureLayer,
|
|
131
|
+
tableTemplate: {
|
|
132
|
+
columnTemplates: [
|
|
133
|
+
new FieldColumnTemplate({
|
|
134
|
+
fieldName: "name",
|
|
135
|
+
label: "Name",
|
|
136
|
+
sortable: true,
|
|
137
|
+
initialSortPriority: 0,
|
|
138
|
+
direction: "asc"
|
|
139
|
+
}),
|
|
140
|
+
new FieldColumnTemplate({
|
|
141
|
+
fieldName: "status",
|
|
142
|
+
label: "Status",
|
|
143
|
+
menuConfig: {
|
|
144
|
+
items: [{
|
|
145
|
+
label: "Custom Action",
|
|
146
|
+
iconClass: "esri-icon-settings",
|
|
147
|
+
clickFunction: (event) => {
|
|
148
|
+
console.log("Custom action on:", event.feature);
|
|
149
|
+
}
|
|
150
|
+
}]
|
|
151
|
+
}
|
|
152
|
+
}),
|
|
153
|
+
new FieldColumnTemplate({
|
|
154
|
+
fieldName: "value",
|
|
155
|
+
label: "Value ($)",
|
|
156
|
+
textAlign: "right",
|
|
157
|
+
formatFunction: (info) => {
|
|
158
|
+
return `$${info.value.toLocaleString()}`;
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Group Column Template
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
import GroupColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/GroupColumnTemplate.js";
|
|
170
|
+
|
|
171
|
+
const featureTable = new FeatureTable({
|
|
172
|
+
view: view,
|
|
173
|
+
layer: featureLayer,
|
|
174
|
+
tableTemplate: {
|
|
175
|
+
columnTemplates: [
|
|
176
|
+
new GroupColumnTemplate({
|
|
177
|
+
label: "Location",
|
|
178
|
+
columnTemplates: [
|
|
179
|
+
new FieldColumnTemplate({ fieldName: "city", label: "City" }),
|
|
180
|
+
new FieldColumnTemplate({ fieldName: "state", label: "State" }),
|
|
181
|
+
new FieldColumnTemplate({ fieldName: "country", label: "Country" })
|
|
182
|
+
]
|
|
183
|
+
}),
|
|
184
|
+
new GroupColumnTemplate({
|
|
185
|
+
label: "Details",
|
|
186
|
+
columnTemplates: [
|
|
187
|
+
new FieldColumnTemplate({ fieldName: "name", label: "Name" }),
|
|
188
|
+
new FieldColumnTemplate({ fieldName: "type", label: "Type" })
|
|
189
|
+
]
|
|
190
|
+
})
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### FeatureTable Events
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
// Row selection
|
|
200
|
+
featureTable.on("selection-change", (event) => {
|
|
201
|
+
console.log("Added:", event.added);
|
|
202
|
+
console.log("Removed:", event.removed);
|
|
203
|
+
|
|
204
|
+
// Get all selected features
|
|
205
|
+
const selectedFeatures = featureTable.highlightIds.toArray();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Row click (double-click to zoom)
|
|
209
|
+
featureTable.viewModel.on("row-highlight-change", (event) => {
|
|
210
|
+
if (event.feature) {
|
|
211
|
+
view.goTo(event.feature.geometry);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Editing complete
|
|
216
|
+
featureTable.on("edit-complete", (event) => {
|
|
217
|
+
console.log("Edited feature:", event.feature);
|
|
218
|
+
console.log("Updated attributes:", event.attributes);
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Programmatic Selection
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
// Select by ObjectIDs
|
|
226
|
+
featureTable.highlightIds.add(123);
|
|
227
|
+
featureTable.highlightIds.addMany([124, 125, 126]);
|
|
228
|
+
|
|
229
|
+
// Clear selection
|
|
230
|
+
featureTable.highlightIds.removeAll();
|
|
231
|
+
|
|
232
|
+
// Select from query
|
|
233
|
+
const results = await featureLayer.queryObjectIds({
|
|
234
|
+
where: "status = 'active'"
|
|
235
|
+
});
|
|
236
|
+
featureTable.highlightIds.addMany(results);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Filter and Refresh
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// Filter by geometry
|
|
243
|
+
featureTable.filterGeometry = view.extent;
|
|
244
|
+
|
|
245
|
+
// Filter by expression
|
|
246
|
+
featureTable.layer.definitionExpression = "category = 'A'";
|
|
247
|
+
|
|
248
|
+
// Refresh data
|
|
249
|
+
featureTable.refresh();
|
|
250
|
+
|
|
251
|
+
// Clear filters
|
|
252
|
+
featureTable.filterGeometry = null;
|
|
253
|
+
featureTable.layer.definitionExpression = null;
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Sync with Map Selection
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// Map click selects in table
|
|
260
|
+
view.on("click", async (event) => {
|
|
261
|
+
const response = await view.hitTest(event);
|
|
262
|
+
const feature = response.results.find(r => r.layer === featureLayer);
|
|
263
|
+
|
|
264
|
+
if (feature) {
|
|
265
|
+
featureTable.highlightIds.removeAll();
|
|
266
|
+
featureTable.highlightIds.add(feature.graphic.attributes.OBJECTID);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Table selection highlights on map
|
|
271
|
+
featureTable.on("selection-change", async (event) => {
|
|
272
|
+
const layerView = await view.whenLayerView(featureLayer);
|
|
273
|
+
|
|
274
|
+
if (highlightHandle) {
|
|
275
|
+
highlightHandle.remove();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const objectIds = featureTable.highlightIds.toArray();
|
|
279
|
+
if (objectIds.length > 0) {
|
|
280
|
+
const query = featureLayer.createQuery();
|
|
281
|
+
query.objectIds = objectIds;
|
|
282
|
+
const results = await featureLayer.queryFeatures(query);
|
|
283
|
+
highlightHandle = layerView.highlight(results.features);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## FormTemplate
|
|
289
|
+
|
|
290
|
+
Configure edit forms for features.
|
|
291
|
+
|
|
292
|
+
### Basic FormTemplate
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
import FormTemplate from "@arcgis/core/form/FormTemplate.js";
|
|
296
|
+
|
|
297
|
+
const formTemplate = new FormTemplate({
|
|
298
|
+
title: "Edit Feature",
|
|
299
|
+
description: "Update the feature attributes",
|
|
300
|
+
elements: [
|
|
301
|
+
{
|
|
302
|
+
type: "field",
|
|
303
|
+
fieldName: "name",
|
|
304
|
+
label: "Name"
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
type: "field",
|
|
308
|
+
fieldName: "category",
|
|
309
|
+
label: "Category"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
type: "field",
|
|
313
|
+
fieldName: "description",
|
|
314
|
+
label: "Description"
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
featureLayer.formTemplate = formTemplate;
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Field Elements
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
import FieldElement from "@arcgis/core/form/elements/FieldElement.js";
|
|
326
|
+
|
|
327
|
+
const fieldElement = new FieldElement({
|
|
328
|
+
fieldName: "name",
|
|
329
|
+
label: "Name",
|
|
330
|
+
description: "Enter the feature name",
|
|
331
|
+
hint: "Required field",
|
|
332
|
+
requiredExpression: "true",
|
|
333
|
+
editableExpression: "$feature.status != 'locked'",
|
|
334
|
+
visibilityExpression: "$feature.type != 'hidden'"
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Group Elements
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
import GroupElement from "@arcgis/core/form/elements/GroupElement.js";
|
|
342
|
+
|
|
343
|
+
const formTemplate = new FormTemplate({
|
|
344
|
+
elements: [
|
|
345
|
+
new GroupElement({
|
|
346
|
+
label: "Basic Information",
|
|
347
|
+
description: "Enter basic details",
|
|
348
|
+
elements: [
|
|
349
|
+
{ type: "field", fieldName: "name", label: "Name" },
|
|
350
|
+
{ type: "field", fieldName: "type", label: "Type" }
|
|
351
|
+
]
|
|
352
|
+
}),
|
|
353
|
+
new GroupElement({
|
|
354
|
+
label: "Location",
|
|
355
|
+
initialState: "collapsed", // expanded, collapsed
|
|
356
|
+
elements: [
|
|
357
|
+
{ type: "field", fieldName: "address", label: "Address" },
|
|
358
|
+
{ type: "field", fieldName: "city", label: "City" },
|
|
359
|
+
{ type: "field", fieldName: "state", label: "State" }
|
|
360
|
+
]
|
|
361
|
+
})
|
|
362
|
+
]
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Text Elements
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
import TextElement from "@arcgis/core/form/elements/TextElement.js";
|
|
370
|
+
|
|
371
|
+
const formTemplate = new FormTemplate({
|
|
372
|
+
elements: [
|
|
373
|
+
new TextElement({
|
|
374
|
+
type: "text",
|
|
375
|
+
text: "<h3>Important Instructions</h3><p>Please fill out all required fields.</p>"
|
|
376
|
+
}),
|
|
377
|
+
{ type: "field", fieldName: "name", label: "Name" },
|
|
378
|
+
new TextElement({
|
|
379
|
+
text: "<hr><small>Fields below are optional</small>"
|
|
380
|
+
}),
|
|
381
|
+
{ type: "field", fieldName: "notes", label: "Notes" }
|
|
382
|
+
]
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Relationship Elements
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
import RelationshipElement from "@arcgis/core/form/elements/RelationshipElement.js";
|
|
390
|
+
|
|
391
|
+
const formTemplate = new FormTemplate({
|
|
392
|
+
elements: [
|
|
393
|
+
{ type: "field", fieldName: "name", label: "Name" },
|
|
394
|
+
new RelationshipElement({
|
|
395
|
+
relationshipId: 0,
|
|
396
|
+
label: "Related Inspections",
|
|
397
|
+
description: "View and manage related inspection records",
|
|
398
|
+
displayCount: 5,
|
|
399
|
+
orderByFields: [{
|
|
400
|
+
field: "inspection_date",
|
|
401
|
+
order: "desc"
|
|
402
|
+
}],
|
|
403
|
+
editableExpression: "true"
|
|
404
|
+
})
|
|
405
|
+
]
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Input Types
|
|
410
|
+
|
|
411
|
+
### TextBox Input
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
{
|
|
415
|
+
type: "field",
|
|
416
|
+
fieldName: "name",
|
|
417
|
+
label: "Name",
|
|
418
|
+
input: {
|
|
419
|
+
type: "text-box",
|
|
420
|
+
maxLength: 100,
|
|
421
|
+
minLength: 1
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### TextArea Input
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
{
|
|
430
|
+
type: "field",
|
|
431
|
+
fieldName: "description",
|
|
432
|
+
label: "Description",
|
|
433
|
+
input: {
|
|
434
|
+
type: "text-area",
|
|
435
|
+
maxLength: 1000,
|
|
436
|
+
minLength: 0
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### ComboBox Input
|
|
442
|
+
|
|
443
|
+
```javascript
|
|
444
|
+
{
|
|
445
|
+
type: "field",
|
|
446
|
+
fieldName: "category",
|
|
447
|
+
label: "Category",
|
|
448
|
+
input: {
|
|
449
|
+
type: "combo-box",
|
|
450
|
+
showNoValueOption: true,
|
|
451
|
+
noValueOptionLabel: "Select a category..."
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Works with coded value domains
|
|
456
|
+
// Domain values automatically populate the combo box
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Radio Buttons Input
|
|
460
|
+
|
|
461
|
+
```javascript
|
|
462
|
+
{
|
|
463
|
+
type: "field",
|
|
464
|
+
fieldName: "priority",
|
|
465
|
+
label: "Priority",
|
|
466
|
+
input: {
|
|
467
|
+
type: "radio-buttons",
|
|
468
|
+
showNoValueOption: false
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Switch Input
|
|
474
|
+
|
|
475
|
+
```javascript
|
|
476
|
+
{
|
|
477
|
+
type: "field",
|
|
478
|
+
fieldName: "is_active",
|
|
479
|
+
label: "Active",
|
|
480
|
+
input: {
|
|
481
|
+
type: "switch",
|
|
482
|
+
offValue: 0,
|
|
483
|
+
onValue: 1
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### DatePicker Input
|
|
489
|
+
|
|
490
|
+
```javascript
|
|
491
|
+
{
|
|
492
|
+
type: "field",
|
|
493
|
+
fieldName: "start_date",
|
|
494
|
+
label: "Start Date",
|
|
495
|
+
input: {
|
|
496
|
+
type: "date-picker",
|
|
497
|
+
min: new Date("2020-01-01"),
|
|
498
|
+
max: new Date("2030-12-31"),
|
|
499
|
+
includeTime: false
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### DateTimePicker Input
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
{
|
|
508
|
+
type: "field",
|
|
509
|
+
fieldName: "event_datetime",
|
|
510
|
+
label: "Event Date/Time",
|
|
511
|
+
input: {
|
|
512
|
+
type: "datetime-picker",
|
|
513
|
+
min: new Date("2020-01-01T00:00:00"),
|
|
514
|
+
max: new Date("2030-12-31T23:59:59"),
|
|
515
|
+
includeTime: true
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### TimePicker Input
|
|
521
|
+
|
|
522
|
+
```javascript
|
|
523
|
+
{
|
|
524
|
+
type: "field",
|
|
525
|
+
fieldName: "event_time",
|
|
526
|
+
label: "Event Time",
|
|
527
|
+
input: {
|
|
528
|
+
type: "time-picker"
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Barcode Scanner Input
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
{
|
|
537
|
+
type: "field",
|
|
538
|
+
fieldName: "barcode",
|
|
539
|
+
label: "Barcode",
|
|
540
|
+
input: {
|
|
541
|
+
type: "barcode-scanner"
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Expression-Based Configuration
|
|
547
|
+
|
|
548
|
+
### Visibility Expressions
|
|
549
|
+
|
|
550
|
+
```javascript
|
|
551
|
+
const formTemplate = new FormTemplate({
|
|
552
|
+
expressionInfos: [
|
|
553
|
+
{
|
|
554
|
+
name: "show-commercial-fields",
|
|
555
|
+
expression: "$feature.property_type == 'commercial'"
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
name: "show-residential-fields",
|
|
559
|
+
expression: "$feature.property_type == 'residential'"
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
elements: [
|
|
563
|
+
{ type: "field", fieldName: "property_type", label: "Property Type" },
|
|
564
|
+
{
|
|
565
|
+
type: "group",
|
|
566
|
+
label: "Commercial Details",
|
|
567
|
+
visibilityExpression: "show-commercial-fields",
|
|
568
|
+
elements: [
|
|
569
|
+
{ type: "field", fieldName: "business_name", label: "Business Name" },
|
|
570
|
+
{ type: "field", fieldName: "num_employees", label: "Employees" }
|
|
571
|
+
]
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
type: "group",
|
|
575
|
+
label: "Residential Details",
|
|
576
|
+
visibilityExpression: "show-residential-fields",
|
|
577
|
+
elements: [
|
|
578
|
+
{ type: "field", fieldName: "num_bedrooms", label: "Bedrooms" },
|
|
579
|
+
{ type: "field", fieldName: "num_bathrooms", label: "Bathrooms" }
|
|
580
|
+
]
|
|
581
|
+
}
|
|
582
|
+
]
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### Required Expressions
|
|
587
|
+
|
|
588
|
+
```javascript
|
|
589
|
+
{
|
|
590
|
+
type: "field",
|
|
591
|
+
fieldName: "inspection_notes",
|
|
592
|
+
label: "Inspection Notes",
|
|
593
|
+
requiredExpression: "$feature.inspection_result == 'failed'"
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### Editable Expressions
|
|
598
|
+
|
|
599
|
+
```javascript
|
|
600
|
+
{
|
|
601
|
+
type: "field",
|
|
602
|
+
fieldName: "approved_by",
|
|
603
|
+
label: "Approved By",
|
|
604
|
+
editableExpression: "$feature.status == 'pending'"
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
## FeatureForm Widget
|
|
609
|
+
|
|
610
|
+
Widget for editing feature attributes.
|
|
611
|
+
|
|
612
|
+
```javascript
|
|
613
|
+
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
|
|
614
|
+
|
|
615
|
+
const featureForm = new FeatureForm({
|
|
616
|
+
container: "formDiv",
|
|
617
|
+
layer: featureLayer,
|
|
618
|
+
formTemplate: formTemplate
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// Set feature to edit
|
|
622
|
+
featureForm.feature = selectedGraphic;
|
|
623
|
+
|
|
624
|
+
// Listen for submit
|
|
625
|
+
featureForm.on("submit", () => {
|
|
626
|
+
if (featureForm.feature) {
|
|
627
|
+
const updated = featureForm.getValues();
|
|
628
|
+
|
|
629
|
+
featureLayer.applyEdits({
|
|
630
|
+
updateFeatures: [{
|
|
631
|
+
attributes: {
|
|
632
|
+
...featureForm.feature.attributes,
|
|
633
|
+
...updated
|
|
634
|
+
},
|
|
635
|
+
geometry: featureForm.feature.geometry
|
|
636
|
+
}]
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Handle value changes
|
|
642
|
+
featureForm.on("value-change", (event) => {
|
|
643
|
+
console.log(`${event.fieldName} changed to ${event.value}`);
|
|
644
|
+
});
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
## AttributeTableTemplate
|
|
648
|
+
|
|
649
|
+
Configure attribute table in Editor widget.
|
|
650
|
+
|
|
651
|
+
```javascript
|
|
652
|
+
import AttributeTableTemplate from "@arcgis/core/widgets/Editor/support/AttributeTableTemplate.js";
|
|
653
|
+
import AttributeTableFieldElement from "@arcgis/core/widgets/Editor/support/AttributeTableFieldElement.js";
|
|
654
|
+
|
|
655
|
+
const tableTemplate = new AttributeTableTemplate({
|
|
656
|
+
elements: [
|
|
657
|
+
new AttributeTableFieldElement({
|
|
658
|
+
fieldName: "name",
|
|
659
|
+
label: "Name",
|
|
660
|
+
editable: true
|
|
661
|
+
}),
|
|
662
|
+
new AttributeTableFieldElement({
|
|
663
|
+
fieldName: "status",
|
|
664
|
+
label: "Status",
|
|
665
|
+
editable: true
|
|
666
|
+
})
|
|
667
|
+
]
|
|
668
|
+
});
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## Editor Widget Integration
|
|
672
|
+
|
|
673
|
+
```javascript
|
|
674
|
+
import Editor from "@arcgis/core/widgets/Editor.js";
|
|
675
|
+
|
|
676
|
+
const editor = new Editor({
|
|
677
|
+
view: view,
|
|
678
|
+
layerInfos: [{
|
|
679
|
+
layer: featureLayer,
|
|
680
|
+
formTemplate: formTemplate,
|
|
681
|
+
enabled: true,
|
|
682
|
+
addEnabled: true,
|
|
683
|
+
updateEnabled: true,
|
|
684
|
+
deleteEnabled: true
|
|
685
|
+
}]
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
view.ui.add(editor, "top-right");
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
## Common Patterns
|
|
692
|
+
|
|
693
|
+
### Complete Form Setup
|
|
694
|
+
|
|
695
|
+
```javascript
|
|
696
|
+
const formTemplate = new FormTemplate({
|
|
697
|
+
title: "Property Information",
|
|
698
|
+
description: "Enter property details",
|
|
699
|
+
preserveFieldValuesWhenHidden: true,
|
|
700
|
+
expressionInfos: [
|
|
701
|
+
{
|
|
702
|
+
name: "is-commercial",
|
|
703
|
+
expression: "$feature.type == 'commercial'"
|
|
704
|
+
}
|
|
705
|
+
],
|
|
706
|
+
elements: [
|
|
707
|
+
// Header text
|
|
708
|
+
{
|
|
709
|
+
type: "text",
|
|
710
|
+
text: "<b>Basic Information</b>"
|
|
711
|
+
},
|
|
712
|
+
// Required field
|
|
713
|
+
{
|
|
714
|
+
type: "field",
|
|
715
|
+
fieldName: "name",
|
|
716
|
+
label: "Property Name",
|
|
717
|
+
requiredExpression: "true",
|
|
718
|
+
input: { type: "text-box", maxLength: 100 }
|
|
719
|
+
},
|
|
720
|
+
// Dropdown
|
|
721
|
+
{
|
|
722
|
+
type: "field",
|
|
723
|
+
fieldName: "type",
|
|
724
|
+
label: "Property Type",
|
|
725
|
+
input: { type: "combo-box" }
|
|
726
|
+
},
|
|
727
|
+
// Conditional group
|
|
728
|
+
{
|
|
729
|
+
type: "group",
|
|
730
|
+
label: "Commercial Details",
|
|
731
|
+
visibilityExpression: "is-commercial",
|
|
732
|
+
elements: [
|
|
733
|
+
{ type: "field", fieldName: "business_type", label: "Business Type" },
|
|
734
|
+
{ type: "field", fieldName: "sqft", label: "Square Footage" }
|
|
735
|
+
]
|
|
736
|
+
},
|
|
737
|
+
// Date field
|
|
738
|
+
{
|
|
739
|
+
type: "field",
|
|
740
|
+
fieldName: "inspection_date",
|
|
741
|
+
label: "Last Inspection",
|
|
742
|
+
input: { type: "date-picker" }
|
|
743
|
+
},
|
|
744
|
+
// Long text
|
|
745
|
+
{
|
|
746
|
+
type: "field",
|
|
747
|
+
fieldName: "notes",
|
|
748
|
+
label: "Notes",
|
|
749
|
+
input: { type: "text-area", maxLength: 500 }
|
|
750
|
+
}
|
|
751
|
+
]
|
|
752
|
+
});
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
### FeatureTable with Editing
|
|
756
|
+
|
|
757
|
+
```javascript
|
|
758
|
+
const featureTable = new FeatureTable({
|
|
759
|
+
view: view,
|
|
760
|
+
layer: featureLayer,
|
|
761
|
+
container: "tableDiv",
|
|
762
|
+
editingEnabled: true,
|
|
763
|
+
fieldConfigs: [
|
|
764
|
+
{ name: "name", label: "Name", editable: true },
|
|
765
|
+
{ name: "status", label: "Status", editable: true },
|
|
766
|
+
{ name: "created_date", label: "Created", editable: false }
|
|
767
|
+
]
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
featureTable.on("edit-complete", async (event) => {
|
|
771
|
+
console.log("Edit saved:", event.feature.attributes);
|
|
772
|
+
|
|
773
|
+
// Refresh related data
|
|
774
|
+
await featureLayer.refresh();
|
|
775
|
+
});
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### Responsive Table Layout
|
|
779
|
+
|
|
780
|
+
```javascript
|
|
781
|
+
const featureTable = new FeatureTable({
|
|
782
|
+
view: view,
|
|
783
|
+
layer: featureLayer,
|
|
784
|
+
container: "tableDiv",
|
|
785
|
+
autoRefreshEnabled: true,
|
|
786
|
+
pageSize: 25
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
// Resize handling
|
|
790
|
+
window.addEventListener("resize", () => {
|
|
791
|
+
featureTable.refresh();
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
// Toggle visibility
|
|
795
|
+
function toggleTable(visible) {
|
|
796
|
+
document.getElementById("tableDiv").style.display = visible ? "block" : "none";
|
|
797
|
+
if (visible) {
|
|
798
|
+
featureTable.refresh();
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
## TypeScript Usage
|
|
804
|
+
|
|
805
|
+
Form elements use autocasting with `type` properties. For TypeScript safety, use `as const`:
|
|
806
|
+
|
|
807
|
+
```typescript
|
|
808
|
+
// Use 'as const' for type safety in form templates
|
|
809
|
+
const formTemplate = {
|
|
810
|
+
title: "Edit Feature",
|
|
811
|
+
elements: [
|
|
812
|
+
{
|
|
813
|
+
type: "field",
|
|
814
|
+
fieldName: "name",
|
|
815
|
+
label: "Name"
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
type: "group",
|
|
819
|
+
label: "Address",
|
|
820
|
+
elements: [
|
|
821
|
+
{ type: "field", fieldName: "street" },
|
|
822
|
+
{ type: "field", fieldName: "city" }
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
} as const;
|
|
827
|
+
|
|
828
|
+
// For input types
|
|
829
|
+
const formElement = {
|
|
830
|
+
type: "field",
|
|
831
|
+
fieldName: "status",
|
|
832
|
+
input: { type: "combo-box" }
|
|
833
|
+
} as const;
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
> **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
|
|
837
|
+
|
|
838
|
+
## Common Pitfalls
|
|
839
|
+
|
|
840
|
+
1. **Field Names Must Match**: fieldName must exactly match layer field
|
|
841
|
+
```javascript
|
|
842
|
+
// Layer has field "PropertyName"
|
|
843
|
+
{ fieldName: "PropertyName" } // Correct
|
|
844
|
+
{ fieldName: "propertyname" } // Wrong - case sensitive
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
2. **Coded Value Domains**: ComboBox auto-populates from domain
|
|
848
|
+
```javascript
|
|
849
|
+
// If field has coded value domain, values come from domain
|
|
850
|
+
{ type: "field", fieldName: "status", input: { type: "combo-box" } }
|
|
851
|
+
// Dropdown shows domain values automatically
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
3. **Expression Names**: Reference expressions by name string
|
|
855
|
+
```javascript
|
|
856
|
+
expressionInfos: [{ name: "my-expr", expression: "..." }],
|
|
857
|
+
elements: [{
|
|
858
|
+
visibilityExpression: "my-expr" // String reference
|
|
859
|
+
}]
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
4. **Layer Must Be Editable**: For edit features to work
|
|
863
|
+
```javascript
|
|
864
|
+
// Layer capabilities must include editing
|
|
865
|
+
if (layer.capabilities.editing.supportsUpdateByOthers) {
|
|
866
|
+
featureTable.editingEnabled = true;
|
|
867
|
+
}
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
5. **Container Size**: Table needs explicit height
|
|
871
|
+
```css
|
|
872
|
+
#tableDiv {
|
|
873
|
+
height: 400px; /* Required */
|
|
874
|
+
width: 100%;
|
|
875
|
+
}
|
|
876
|
+
```
|
|
877
|
+
|