@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.
Files changed (50) hide show
  1. package/README.md +163 -201
  2. package/bin/cli.js +157 -173
  3. package/contexts/4.34/{claude → skills}/arcgis-3d-advanced/SKILL.md +586 -586
  4. package/contexts/4.34/{claude → skills}/arcgis-advanced-layers/SKILL.md +431 -431
  5. package/contexts/4.34/{claude → skills}/arcgis-analysis-services/SKILL.md +607 -607
  6. package/contexts/4.34/{claude → skills}/arcgis-authentication/SKILL.md +301 -301
  7. package/contexts/4.34/{claude → skills}/arcgis-cim-symbols/SKILL.md +486 -486
  8. package/contexts/4.34/{claude → skills}/arcgis-coordinates-projection/SKILL.md +406 -406
  9. package/contexts/4.34/{claude → skills}/arcgis-core-maps/SKILL.md +739 -739
  10. package/contexts/4.34/{claude → skills}/arcgis-core-utilities/SKILL.md +732 -732
  11. package/contexts/4.34/{claude → skills}/arcgis-custom-rendering/SKILL.md +445 -445
  12. package/contexts/4.34/{claude → skills}/arcgis-editing-advanced/SKILL.md +702 -702
  13. package/contexts/4.34/{claude → skills}/arcgis-feature-effects/SKILL.md +393 -393
  14. package/contexts/4.34/{claude → skills}/arcgis-geometry-operations/SKILL.md +489 -489
  15. package/contexts/4.34/{claude → skills}/arcgis-imagery/SKILL.md +307 -307
  16. package/contexts/4.34/{claude → skills}/arcgis-interaction/SKILL.md +572 -572
  17. package/contexts/4.34/{claude → skills}/arcgis-knowledge-graphs/SKILL.md +582 -582
  18. package/contexts/4.34/{claude → skills}/arcgis-layers/SKILL.md +601 -601
  19. package/contexts/4.34/{claude → skills}/arcgis-map-tools/SKILL.md +668 -668
  20. package/contexts/4.34/{claude → skills}/arcgis-media-layers/SKILL.md +290 -290
  21. package/contexts/4.34/{claude → skills}/arcgis-portal-content/SKILL.md +679 -679
  22. package/contexts/4.34/{claude → skills}/arcgis-scene-effects/SKILL.md +512 -512
  23. package/contexts/4.34/{claude → skills}/arcgis-smart-mapping/SKILL.md +686 -686
  24. package/contexts/4.34/skills/arcgis-starter-app/SKILL.md +273 -0
  25. package/contexts/4.34/skills/arcgis-starter-app-extended/SKILL.md +649 -0
  26. package/contexts/4.34/{claude → skills}/arcgis-tables-forms/SKILL.md +877 -877
  27. package/contexts/4.34/{claude → skills}/arcgis-time-animation/SKILL.md +722 -722
  28. package/contexts/4.34/{claude → skills}/arcgis-utility-networks/SKILL.md +301 -301
  29. package/contexts/4.34/{claude → skills}/arcgis-visualization/SKILL.md +580 -580
  30. package/contexts/4.34/{claude → skills}/arcgis-widgets-ui/SKILL.md +574 -574
  31. package/lib/installer.js +294 -379
  32. package/package.json +45 -45
  33. package/contexts/4.34/copilot/arcgis-3d.instructions.md +0 -267
  34. package/contexts/4.34/copilot/arcgis-analysis.instructions.md +0 -294
  35. package/contexts/4.34/copilot/arcgis-arcade.instructions.md +0 -234
  36. package/contexts/4.34/copilot/arcgis-authentication.instructions.md +0 -187
  37. package/contexts/4.34/copilot/arcgis-cim-symbols.instructions.md +0 -177
  38. package/contexts/4.34/copilot/arcgis-core-maps.instructions.md +0 -246
  39. package/contexts/4.34/copilot/arcgis-core-utilities.instructions.md +0 -247
  40. package/contexts/4.34/copilot/arcgis-editing.instructions.md +0 -262
  41. package/contexts/4.34/copilot/arcgis-geometry.instructions.md +0 -225
  42. package/contexts/4.34/copilot/arcgis-layers.instructions.md +0 -278
  43. package/contexts/4.34/copilot/arcgis-popup-templates.instructions.md +0 -266
  44. package/contexts/4.34/copilot/arcgis-portal-advanced.instructions.md +0 -275
  45. package/contexts/4.34/copilot/arcgis-smart-mapping.instructions.md +0 -184
  46. package/contexts/4.34/copilot/arcgis-time-animation.instructions.md +0 -112
  47. package/contexts/4.34/copilot/arcgis-visualization.instructions.md +0 -321
  48. package/contexts/4.34/copilot/arcgis-widgets-ui.instructions.md +0 -277
  49. /package/contexts/4.34/{claude → skills}/arcgis-arcade/SKILL.md +0 -0
  50. /package/contexts/4.34/{claude → skills}/arcgis-popup-templates/SKILL.md +0 -0
@@ -1,702 +1,702 @@
1
- ---
2
- name: arcgis-editing-advanced
3
- description: Advanced editing features including subtypes, feature forms, versioning, and configurable editors. Use for complex data entry workflows.
4
- ---
5
-
6
- # ArcGIS Advanced Editing
7
-
8
- Use this skill for advanced editing features including subtypes, forms, versioning, and editor configuration.
9
-
10
- > **Note:** For basic editing, use the `arcgis-editor` component. This skill covers advanced configurations that require the Core API.
11
-
12
- ## Editor Component (Basic)
13
-
14
- ```html
15
- <arcgis-map item-id="YOUR_EDITABLE_WEBMAP_ID">
16
- <arcgis-editor slot="top-right"></arcgis-editor>
17
- </arcgis-map>
18
- ```
19
-
20
- ## Editor Configuration (Advanced)
21
-
22
- ### Configurable Editor
23
- ```javascript
24
- import Editor from "@arcgis/core/widgets/Editor.js";
25
-
26
- const editor = new Editor({
27
- view: view,
28
- layerInfos: [{
29
- layer: featureLayer,
30
- formTemplate: {
31
- title: "Feature Details",
32
- description: "Enter feature information",
33
- elements: [
34
- {
35
- type: "field",
36
- fieldName: "name",
37
- label: "Name",
38
- description: "Enter the feature name"
39
- },
40
- {
41
- type: "field",
42
- fieldName: "category",
43
- label: "Category"
44
- }
45
- ]
46
- },
47
- // Enable/disable operations
48
- addEnabled: true,
49
- updateEnabled: true,
50
- deleteEnabled: false
51
- }]
52
- });
53
-
54
- view.ui.add(editor, "top-right");
55
- ```
56
-
57
- ### Editor with Field Configuration
58
- ```javascript
59
- const editor = new Editor({
60
- view: view,
61
- layerInfos: [{
62
- layer: featureLayer,
63
- fieldConfig: [
64
- {
65
- name: "status",
66
- label: "Status",
67
- editable: true,
68
- required: true
69
- },
70
- {
71
- name: "created_date",
72
- label: "Created",
73
- editable: false // Read-only
74
- },
75
- {
76
- name: "comments",
77
- label: "Comments",
78
- editable: true,
79
- maxLength: 500
80
- }
81
- ]
82
- }]
83
- });
84
- ```
85
-
86
- ## Feature Form
87
-
88
- ### Standalone Feature Form
89
- ```javascript
90
- import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
91
-
92
- const form = new FeatureForm({
93
- container: "formDiv",
94
- layer: featureLayer,
95
- formTemplate: {
96
- title: "Edit Feature",
97
- elements: [
98
- {
99
- type: "field",
100
- fieldName: "name",
101
- label: "Name"
102
- },
103
- {
104
- type: "group",
105
- label: "Location Details",
106
- elements: [
107
- { type: "field", fieldName: "address" },
108
- { type: "field", fieldName: "city" },
109
- { type: "field", fieldName: "zip" }
110
- ]
111
- }
112
- ]
113
- }
114
- });
115
-
116
- // Set feature to edit
117
- form.feature = graphic;
118
-
119
- // Listen for submit
120
- form.on("submit", async () => {
121
- if (form.valid) {
122
- const values = form.getValues();
123
- graphic.attributes = { ...graphic.attributes, ...values };
124
- await featureLayer.applyEdits({
125
- updateFeatures: [graphic]
126
- });
127
- }
128
- });
129
- ```
130
-
131
- ### Form with Grouped Elements
132
- ```javascript
133
- const formTemplate = {
134
- title: "Asset Details",
135
- elements: [
136
- {
137
- type: "group",
138
- label: "Basic Information",
139
- elements: [
140
- { type: "field", fieldName: "asset_id" },
141
- { type: "field", fieldName: "asset_name" },
142
- { type: "field", fieldName: "asset_type" }
143
- ]
144
- },
145
- {
146
- type: "group",
147
- label: "Maintenance",
148
- elements: [
149
- { type: "field", fieldName: "last_inspection" },
150
- { type: "field", fieldName: "next_inspection" },
151
- { type: "field", fieldName: "condition" }
152
- ]
153
- }
154
- ]
155
- };
156
- ```
157
-
158
- ### Expression-Based Visibility
159
- ```javascript
160
- const formTemplate = {
161
- elements: [
162
- {
163
- type: "field",
164
- fieldName: "type"
165
- },
166
- {
167
- type: "field",
168
- fieldName: "subtype",
169
- visibilityExpression: "type-requires-subtype"
170
- }
171
- ],
172
- expressionInfos: [{
173
- name: "type-requires-subtype",
174
- expression: "$feature.type == 'complex'"
175
- }]
176
- };
177
- ```
178
-
179
- ## Subtypes
180
-
181
- ### Working with Subtypes
182
- ```javascript
183
- // Layer with subtypes
184
- const layer = new FeatureLayer({
185
- url: "https://services.arcgis.com/.../FeatureServer/0"
186
- });
187
-
188
- await layer.load();
189
-
190
- // Get subtype info
191
- const subtypeField = layer.subtypeField;
192
- const subtypes = layer.subtypes;
193
-
194
- subtypes.forEach(subtype => {
195
- console.log("Code:", subtype.code);
196
- console.log("Name:", subtype.name);
197
- console.log("Default values:", subtype.defaultValues);
198
- });
199
- ```
200
-
201
- ### Subtype Group Layer
202
- ```javascript
203
- import SubtypeGroupLayer from "@arcgis/core/layers/SubtypeGroupLayer.js";
204
-
205
- const subtypeLayer = new SubtypeGroupLayer({
206
- url: "https://services.arcgis.com/.../FeatureServer/0"
207
- });
208
-
209
- await subtypeLayer.load();
210
-
211
- // Access sublayers by subtype
212
- subtypeLayer.sublayers.forEach(sublayer => {
213
- console.log("Subtype:", sublayer.subtypeCode, sublayer.title);
214
- // Each sublayer can have different renderer/popup
215
- });
216
- ```
217
-
218
- ### Editor with Subtype Support
219
- ```javascript
220
- const editor = new Editor({
221
- view: view,
222
- layerInfos: [{
223
- layer: subtypeGroupLayer,
224
- // Editor automatically handles subtypes
225
- addEnabled: true,
226
- updateEnabled: true
227
- }]
228
- });
229
- ```
230
-
231
- ## Versioning
232
-
233
- ### Branch Versioning Overview
234
-
235
- Branch versioning allows multiple users to edit the same data simultaneously without conflicts until reconciliation.
236
-
237
- ```javascript
238
- import VersionManagementService from "@arcgis/core/versionManagement/VersionManagementService.js";
239
-
240
- const vms = new VersionManagementService({
241
- url: "https://services.arcgis.com/.../VersionManagementServer"
242
- });
243
-
244
- await vms.load();
245
-
246
- console.log("Default version:", vms.defaultVersionName);
247
- console.log("Supports versioning:", vms.supportsVersioning);
248
- ```
249
-
250
- ### Get Version Information
251
-
252
- ```javascript
253
- // Get all versions
254
- const versions = await vms.getVersionInfos();
255
- versions.forEach(v => {
256
- console.log("Version:", v.versionName);
257
- console.log(" Owner:", v.versionOwner);
258
- console.log(" Description:", v.description);
259
- console.log(" Access:", v.access); // public, protected, private
260
- console.log(" Parent:", v.parentVersionName);
261
- console.log(" Created:", v.creationDate);
262
- console.log(" Modified:", v.modifiedDate);
263
- });
264
-
265
- // Get specific version info
266
- const versionInfo = await vms.getVersionInfo({
267
- versionName: "sde.MyVersion"
268
- });
269
- ```
270
-
271
- ### Create Version
272
-
273
- ```javascript
274
- // Create new version
275
- const newVersion = await vms.createVersion({
276
- versionName: "MyEditVersion",
277
- description: "Version for editing project X",
278
- access: "private", // public, protected, private
279
- parentVersionName: "sde.DEFAULT" // Optional, defaults to DEFAULT
280
- });
281
-
282
- console.log("Created version:", newVersion.versionName);
283
- console.log("Version GUID:", newVersion.versionGuid);
284
- ```
285
-
286
- ### Delete Version
287
-
288
- ```javascript
289
- // Delete a version (must be owner or admin)
290
- await vms.deleteVersion({
291
- versionName: "sde.MyEditVersion"
292
- });
293
- ```
294
-
295
- ### Alter Version
296
-
297
- ```javascript
298
- // Modify version properties
299
- await vms.alterVersion({
300
- versionName: "sde.MyEditVersion",
301
- description: "Updated description",
302
- access: "protected", // Change access level
303
- ownerName: "newOwner" // Transfer ownership (admin only)
304
- });
305
- ```
306
-
307
- ### Switching Versions
308
-
309
- ```javascript
310
- // Set version on layer at creation
311
- const featureLayer = new FeatureLayer({
312
- url: "https://services.arcgis.com/.../FeatureServer/0",
313
- gdbVersion: "sde.MyEditVersion"
314
- });
315
-
316
- // Or change version dynamically
317
- await featureLayer.load();
318
- featureLayer.gdbVersion = "sde.AnotherVersion";
319
- await featureLayer.refresh();
320
-
321
- // Switch all layers in map
322
- map.layers.forEach(layer => {
323
- if (layer.gdbVersion !== undefined) {
324
- layer.gdbVersion = "sde.MyEditVersion";
325
- layer.refresh();
326
- }
327
- });
328
- ```
329
-
330
- ### Start/Stop Edit Session
331
-
332
- ```javascript
333
- // Start editing session
334
- const session = await vms.startReading({
335
- versionName: "sde.MyEditVersion"
336
- });
337
- const sessionId = session.sessionId;
338
-
339
- // For write access
340
- const writeSession = await vms.startEditing({
341
- versionName: "sde.MyEditVersion"
342
- });
343
-
344
- // Stop session when done
345
- await vms.stopEditing({
346
- sessionId: sessionId,
347
- saveEdits: true // or false to discard
348
- });
349
- ```
350
-
351
- ### Version Reconcile and Post
352
-
353
- ```javascript
354
- // Reconcile version with parent
355
- const reconcileResult = await vms.reconcile({
356
- sessionId: sessionId,
357
- abortIfConflicts: false,
358
- conflictDetection: "byAttribute", // byAttribute, byObject
359
- withPost: false,
360
- conflictResolution: "favorEditVersion" // favorEditVersion, favorTargetVersion
361
- });
362
-
363
- console.log("Has conflicts:", reconcileResult.hasConflicts);
364
- console.log("Conflicts removed:", reconcileResult.conflictsRemoved);
365
-
366
- if (!reconcileResult.hasConflicts) {
367
- // Post changes to parent version
368
- await vms.post({ sessionId });
369
- console.log("Changes posted successfully");
370
- }
371
- ```
372
-
373
- ### Conflict Detection and Resolution
374
-
375
- ```javascript
376
- // Check for conflicts before reconcile
377
- const conflictResult = await vms.reconcile({
378
- sessionId: sessionId,
379
- abortIfConflicts: true, // Stop if conflicts found
380
- conflictDetection: "byAttribute"
381
- });
382
-
383
- if (conflictResult.hasConflicts) {
384
- // Get conflict details
385
- console.log("Conflicts found, manual resolution needed");
386
-
387
- // Resolve conflicts by favoring edit version
388
- const resolveResult = await vms.reconcile({
389
- sessionId: sessionId,
390
- abortIfConflicts: false,
391
- conflictResolution: "favorEditVersion",
392
- withPost: true
393
- });
394
- }
395
- ```
396
-
397
- ### Version Differences
398
-
399
- ```javascript
400
- // Get differences between versions
401
- const differences = await vms.getVersionDifferences({
402
- sessionId: sessionId,
403
- fromMoment: "commonAncestor", // commonAncestor, now
404
- layers: ["0", "1"] // Layer IDs to compare
405
- });
406
-
407
- differences.forEach(diff => {
408
- console.log("Layer:", diff.layerId);
409
- console.log("Inserts:", diff.inserts);
410
- console.log("Updates:", diff.updates);
411
- console.log("Deletes:", diff.deletes);
412
- });
413
- ```
414
-
415
- ### Version Lock Management
416
-
417
- ```javascript
418
- // Get lock status
419
- const lockInfo = await vms.getLockInfo({
420
- versionName: "sde.MyEditVersion"
421
- });
422
-
423
- console.log("Is locked:", lockInfo.isLocked);
424
- console.log("Locked by:", lockInfo.lockOwner);
425
- console.log("Lock type:", lockInfo.lockType);
426
-
427
- // Acquire exclusive lock
428
- await vms.acquireLock({
429
- versionName: "sde.MyEditVersion",
430
- lockType: "exclusive" // shared, exclusive
431
- });
432
-
433
- // Release lock
434
- await vms.releaseLock({
435
- versionName: "sde.MyEditVersion"
436
- });
437
- ```
438
-
439
- ### Validate Network Topology
440
-
441
- ```javascript
442
- // For utility networks - validate topology after edits
443
- const validateResult = await vms.validateNetworkTopology({
444
- sessionId: sessionId,
445
- validateArea: extent, // Optional extent to validate
446
- validationType: "normal" // normal, rebuild
447
- });
448
-
449
- console.log("Validation success:", validateResult.success);
450
- console.log("Dirty areas remaining:", validateResult.dirtyAreaCount);
451
- ```
452
-
453
- ### Complete Version Workflow
454
-
455
- ```javascript
456
- async function editInVersion(vms, featureLayer, edits) {
457
- // 1. Create version
458
- const version = await vms.createVersion({
459
- versionName: `Edit_${Date.now()}`,
460
- description: "Temporary edit version",
461
- access: "private"
462
- });
463
-
464
- try {
465
- // 2. Switch layer to version
466
- featureLayer.gdbVersion = version.versionName;
467
- await featureLayer.refresh();
468
-
469
- // 3. Start edit session
470
- const session = await vms.startEditing({
471
- versionName: version.versionName
472
- });
473
-
474
- // 4. Apply edits
475
- await featureLayer.applyEdits(edits);
476
-
477
- // 5. Reconcile with parent
478
- const reconcileResult = await vms.reconcile({
479
- sessionId: session.sessionId,
480
- abortIfConflicts: false,
481
- conflictResolution: "favorEditVersion",
482
- withPost: false
483
- });
484
-
485
- if (reconcileResult.hasConflicts) {
486
- throw new Error("Conflicts detected during reconcile");
487
- }
488
-
489
- // 6. Post to parent
490
- await vms.post({ sessionId: session.sessionId });
491
-
492
- // 7. Stop editing
493
- await vms.stopEditing({
494
- sessionId: session.sessionId,
495
- saveEdits: true
496
- });
497
-
498
- console.log("Edits posted successfully");
499
-
500
- } finally {
501
- // 8. Switch back to default and delete temp version
502
- featureLayer.gdbVersion = vms.defaultVersionName;
503
- await featureLayer.refresh();
504
-
505
- await vms.deleteVersion({
506
- versionName: version.versionName
507
- });
508
- }
509
- }
510
- ```
511
-
512
- ## Related Records
513
-
514
- ### Query Related Records
515
- ```javascript
516
- const relatedRecords = await layer.queryRelatedFeatures({
517
- outFields: ["*"],
518
- relationshipId: 0,
519
- objectIds: [selectedFeature.attributes.OBJECTID]
520
- });
521
-
522
- relatedRecords[selectedObjectId].features.forEach(related => {
523
- console.log("Related:", related.attributes);
524
- });
525
- ```
526
-
527
- ### Edit Related Records in Form
528
- ```javascript
529
- const editor = new Editor({
530
- view: view,
531
- layerInfos: [{
532
- layer: parentLayer,
533
- // Include related tables
534
- relatedTableInfos: [{
535
- layer: relatedTable,
536
- addEnabled: true,
537
- updateEnabled: true,
538
- deleteEnabled: true
539
- }]
540
- }]
541
- });
542
- ```
543
-
544
- ## Attachments
545
-
546
- ### Enable Attachments in Editor
547
- ```javascript
548
- const editor = new Editor({
549
- view: view,
550
- layerInfos: [{
551
- layer: featureLayer,
552
- attachmentsOnCreateEnabled: true,
553
- attachmentsOnUpdateEnabled: true
554
- }]
555
- });
556
- ```
557
-
558
- ### Programmatic Attachment Handling
559
- ```javascript
560
- // Query attachments
561
- const attachments = await layer.queryAttachments({
562
- objectIds: [featureOID]
563
- });
564
-
565
- // Add attachment
566
- const formData = new FormData();
567
- formData.append("attachment", fileBlob, "photo.jpg");
568
-
569
- await layer.addAttachment(featureOID, formData);
570
-
571
- // Delete attachment
572
- await layer.deleteAttachments(featureOID, [attachmentId]);
573
- ```
574
-
575
- ## Validation
576
-
577
- ### Form Validation
578
- ```javascript
579
- const form = new FeatureForm({
580
- layer: featureLayer,
581
- formTemplate: {
582
- elements: [{
583
- type: "field",
584
- fieldName: "email",
585
- label: "Email",
586
- validationExpression: {
587
- expression: `
588
- var email = $feature.email;
589
- return IIf(Find("@", email) > 0, true, { valid: false, errorMessage: "Invalid email" });
590
- `
591
- }
592
- }]
593
- }
594
- });
595
-
596
- // Check validity before submit
597
- if (form.valid) {
598
- // Submit
599
- } else {
600
- // Show validation errors
601
- }
602
- ```
603
-
604
- ## Complete Example
605
-
606
- ```html
607
- <!DOCTYPE html>
608
- <html>
609
- <head>
610
- <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
611
- <script src="https://js.arcgis.com/4.34/"></script>
612
- <style>
613
- html, body, #viewDiv { height: 100%; margin: 0; }
614
- #formPanel { position: absolute; top: 10px; right: 10px; width: 300px; }
615
- </style>
616
- <script type="module">
617
- import Map from "@arcgis/core/Map.js";
618
- import MapView from "@arcgis/core/views/MapView.js";
619
- import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
620
- import Editor from "@arcgis/core/widgets/Editor.js";
621
-
622
- const layer = new FeatureLayer({
623
- url: "https://services.arcgis.com/.../FeatureServer/0"
624
- });
625
-
626
- const map = new Map({
627
- basemap: "streets-navigation-vector",
628
- layers: [layer]
629
- });
630
-
631
- const view = new MapView({
632
- container: "viewDiv",
633
- map: map
634
- });
635
-
636
- const editor = new Editor({
637
- view: view,
638
- layerInfos: [{
639
- layer: layer,
640
- formTemplate: {
641
- title: "Edit Feature",
642
- elements: [
643
- {
644
- type: "group",
645
- label: "Details",
646
- elements: [
647
- { type: "field", fieldName: "name", label: "Name" },
648
- { type: "field", fieldName: "type", label: "Type" },
649
- { type: "field", fieldName: "status", label: "Status" }
650
- ]
651
- }
652
- ]
653
- },
654
- attachmentsOnCreateEnabled: true,
655
- attachmentsOnUpdateEnabled: true
656
- }]
657
- });
658
-
659
- view.ui.add(editor, "top-right");
660
- </script>
661
- </head>
662
- <body>
663
- <div id="viewDiv"></div>
664
- </body>
665
- </html>
666
- ```
667
-
668
- ## TypeScript Usage
669
-
670
- Form elements use autocasting with `type` properties. For TypeScript safety, use `as const`:
671
-
672
- ```typescript
673
- // Use 'as const' for type safety in editor configurations
674
- const editor = new Editor({
675
- view: view,
676
- layerInfos: [{
677
- layer: featureLayer,
678
- formTemplate: {
679
- title: "Feature Details",
680
- elements: [
681
- { type: "field", fieldName: "name" },
682
- { type: "field", fieldName: "category" }
683
- ]
684
- } as const
685
- }]
686
- });
687
- ```
688
-
689
- > **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
690
-
691
- ## Common Pitfalls
692
-
693
- 1. **Editing permissions**: User must have edit permissions on the layer
694
-
695
- 2. **Subtype field**: Must match the subtype configuration in the service
696
-
697
- 3. **Version locking**: Branch versions may lock during editing sessions
698
-
699
- 4. **Validation expressions**: Must return true/false or error object
700
-
701
- 5. **Related records**: Require proper relationship configuration in service
702
-
1
+ ---
2
+ name: arcgis-editing-advanced
3
+ description: Advanced editing features including subtypes, feature forms, versioning, and configurable editors. Use for complex data entry workflows.
4
+ ---
5
+
6
+ # ArcGIS Advanced Editing
7
+
8
+ Use this skill for advanced editing features including subtypes, forms, versioning, and editor configuration.
9
+
10
+ > **Note:** For basic editing, use the `arcgis-editor` component. This skill covers advanced configurations that require the Core API.
11
+
12
+ ## Editor Component (Basic)
13
+
14
+ ```html
15
+ <arcgis-map item-id="YOUR_EDITABLE_WEBMAP_ID">
16
+ <arcgis-editor slot="top-right"></arcgis-editor>
17
+ </arcgis-map>
18
+ ```
19
+
20
+ ## Editor Configuration (Advanced)
21
+
22
+ ### Configurable Editor
23
+ ```javascript
24
+ import Editor from "@arcgis/core/widgets/Editor.js";
25
+
26
+ const editor = new Editor({
27
+ view: view,
28
+ layerInfos: [{
29
+ layer: featureLayer,
30
+ formTemplate: {
31
+ title: "Feature Details",
32
+ description: "Enter feature information",
33
+ elements: [
34
+ {
35
+ type: "field",
36
+ fieldName: "name",
37
+ label: "Name",
38
+ description: "Enter the feature name"
39
+ },
40
+ {
41
+ type: "field",
42
+ fieldName: "category",
43
+ label: "Category"
44
+ }
45
+ ]
46
+ },
47
+ // Enable/disable operations
48
+ addEnabled: true,
49
+ updateEnabled: true,
50
+ deleteEnabled: false
51
+ }]
52
+ });
53
+
54
+ view.ui.add(editor, "top-right");
55
+ ```
56
+
57
+ ### Editor with Field Configuration
58
+ ```javascript
59
+ const editor = new Editor({
60
+ view: view,
61
+ layerInfos: [{
62
+ layer: featureLayer,
63
+ fieldConfig: [
64
+ {
65
+ name: "status",
66
+ label: "Status",
67
+ editable: true,
68
+ required: true
69
+ },
70
+ {
71
+ name: "created_date",
72
+ label: "Created",
73
+ editable: false // Read-only
74
+ },
75
+ {
76
+ name: "comments",
77
+ label: "Comments",
78
+ editable: true,
79
+ maxLength: 500
80
+ }
81
+ ]
82
+ }]
83
+ });
84
+ ```
85
+
86
+ ## Feature Form
87
+
88
+ ### Standalone Feature Form
89
+ ```javascript
90
+ import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
91
+
92
+ const form = new FeatureForm({
93
+ container: "formDiv",
94
+ layer: featureLayer,
95
+ formTemplate: {
96
+ title: "Edit Feature",
97
+ elements: [
98
+ {
99
+ type: "field",
100
+ fieldName: "name",
101
+ label: "Name"
102
+ },
103
+ {
104
+ type: "group",
105
+ label: "Location Details",
106
+ elements: [
107
+ { type: "field", fieldName: "address" },
108
+ { type: "field", fieldName: "city" },
109
+ { type: "field", fieldName: "zip" }
110
+ ]
111
+ }
112
+ ]
113
+ }
114
+ });
115
+
116
+ // Set feature to edit
117
+ form.feature = graphic;
118
+
119
+ // Listen for submit
120
+ form.on("submit", async () => {
121
+ if (form.valid) {
122
+ const values = form.getValues();
123
+ graphic.attributes = { ...graphic.attributes, ...values };
124
+ await featureLayer.applyEdits({
125
+ updateFeatures: [graphic]
126
+ });
127
+ }
128
+ });
129
+ ```
130
+
131
+ ### Form with Grouped Elements
132
+ ```javascript
133
+ const formTemplate = {
134
+ title: "Asset Details",
135
+ elements: [
136
+ {
137
+ type: "group",
138
+ label: "Basic Information",
139
+ elements: [
140
+ { type: "field", fieldName: "asset_id" },
141
+ { type: "field", fieldName: "asset_name" },
142
+ { type: "field", fieldName: "asset_type" }
143
+ ]
144
+ },
145
+ {
146
+ type: "group",
147
+ label: "Maintenance",
148
+ elements: [
149
+ { type: "field", fieldName: "last_inspection" },
150
+ { type: "field", fieldName: "next_inspection" },
151
+ { type: "field", fieldName: "condition" }
152
+ ]
153
+ }
154
+ ]
155
+ };
156
+ ```
157
+
158
+ ### Expression-Based Visibility
159
+ ```javascript
160
+ const formTemplate = {
161
+ elements: [
162
+ {
163
+ type: "field",
164
+ fieldName: "type"
165
+ },
166
+ {
167
+ type: "field",
168
+ fieldName: "subtype",
169
+ visibilityExpression: "type-requires-subtype"
170
+ }
171
+ ],
172
+ expressionInfos: [{
173
+ name: "type-requires-subtype",
174
+ expression: "$feature.type == 'complex'"
175
+ }]
176
+ };
177
+ ```
178
+
179
+ ## Subtypes
180
+
181
+ ### Working with Subtypes
182
+ ```javascript
183
+ // Layer with subtypes
184
+ const layer = new FeatureLayer({
185
+ url: "https://services.arcgis.com/.../FeatureServer/0"
186
+ });
187
+
188
+ await layer.load();
189
+
190
+ // Get subtype info
191
+ const subtypeField = layer.subtypeField;
192
+ const subtypes = layer.subtypes;
193
+
194
+ subtypes.forEach(subtype => {
195
+ console.log("Code:", subtype.code);
196
+ console.log("Name:", subtype.name);
197
+ console.log("Default values:", subtype.defaultValues);
198
+ });
199
+ ```
200
+
201
+ ### Subtype Group Layer
202
+ ```javascript
203
+ import SubtypeGroupLayer from "@arcgis/core/layers/SubtypeGroupLayer.js";
204
+
205
+ const subtypeLayer = new SubtypeGroupLayer({
206
+ url: "https://services.arcgis.com/.../FeatureServer/0"
207
+ });
208
+
209
+ await subtypeLayer.load();
210
+
211
+ // Access sublayers by subtype
212
+ subtypeLayer.sublayers.forEach(sublayer => {
213
+ console.log("Subtype:", sublayer.subtypeCode, sublayer.title);
214
+ // Each sublayer can have different renderer/popup
215
+ });
216
+ ```
217
+
218
+ ### Editor with Subtype Support
219
+ ```javascript
220
+ const editor = new Editor({
221
+ view: view,
222
+ layerInfos: [{
223
+ layer: subtypeGroupLayer,
224
+ // Editor automatically handles subtypes
225
+ addEnabled: true,
226
+ updateEnabled: true
227
+ }]
228
+ });
229
+ ```
230
+
231
+ ## Versioning
232
+
233
+ ### Branch Versioning Overview
234
+
235
+ Branch versioning allows multiple users to edit the same data simultaneously without conflicts until reconciliation.
236
+
237
+ ```javascript
238
+ import VersionManagementService from "@arcgis/core/versionManagement/VersionManagementService.js";
239
+
240
+ const vms = new VersionManagementService({
241
+ url: "https://services.arcgis.com/.../VersionManagementServer"
242
+ });
243
+
244
+ await vms.load();
245
+
246
+ console.log("Default version:", vms.defaultVersionName);
247
+ console.log("Supports versioning:", vms.supportsVersioning);
248
+ ```
249
+
250
+ ### Get Version Information
251
+
252
+ ```javascript
253
+ // Get all versions
254
+ const versions = await vms.getVersionInfos();
255
+ versions.forEach(v => {
256
+ console.log("Version:", v.versionName);
257
+ console.log(" Owner:", v.versionOwner);
258
+ console.log(" Description:", v.description);
259
+ console.log(" Access:", v.access); // public, protected, private
260
+ console.log(" Parent:", v.parentVersionName);
261
+ console.log(" Created:", v.creationDate);
262
+ console.log(" Modified:", v.modifiedDate);
263
+ });
264
+
265
+ // Get specific version info
266
+ const versionInfo = await vms.getVersionInfo({
267
+ versionName: "sde.MyVersion"
268
+ });
269
+ ```
270
+
271
+ ### Create Version
272
+
273
+ ```javascript
274
+ // Create new version
275
+ const newVersion = await vms.createVersion({
276
+ versionName: "MyEditVersion",
277
+ description: "Version for editing project X",
278
+ access: "private", // public, protected, private
279
+ parentVersionName: "sde.DEFAULT" // Optional, defaults to DEFAULT
280
+ });
281
+
282
+ console.log("Created version:", newVersion.versionName);
283
+ console.log("Version GUID:", newVersion.versionGuid);
284
+ ```
285
+
286
+ ### Delete Version
287
+
288
+ ```javascript
289
+ // Delete a version (must be owner or admin)
290
+ await vms.deleteVersion({
291
+ versionName: "sde.MyEditVersion"
292
+ });
293
+ ```
294
+
295
+ ### Alter Version
296
+
297
+ ```javascript
298
+ // Modify version properties
299
+ await vms.alterVersion({
300
+ versionName: "sde.MyEditVersion",
301
+ description: "Updated description",
302
+ access: "protected", // Change access level
303
+ ownerName: "newOwner" // Transfer ownership (admin only)
304
+ });
305
+ ```
306
+
307
+ ### Switching Versions
308
+
309
+ ```javascript
310
+ // Set version on layer at creation
311
+ const featureLayer = new FeatureLayer({
312
+ url: "https://services.arcgis.com/.../FeatureServer/0",
313
+ gdbVersion: "sde.MyEditVersion"
314
+ });
315
+
316
+ // Or change version dynamically
317
+ await featureLayer.load();
318
+ featureLayer.gdbVersion = "sde.AnotherVersion";
319
+ await featureLayer.refresh();
320
+
321
+ // Switch all layers in map
322
+ map.layers.forEach(layer => {
323
+ if (layer.gdbVersion !== undefined) {
324
+ layer.gdbVersion = "sde.MyEditVersion";
325
+ layer.refresh();
326
+ }
327
+ });
328
+ ```
329
+
330
+ ### Start/Stop Edit Session
331
+
332
+ ```javascript
333
+ // Start editing session
334
+ const session = await vms.startReading({
335
+ versionName: "sde.MyEditVersion"
336
+ });
337
+ const sessionId = session.sessionId;
338
+
339
+ // For write access
340
+ const writeSession = await vms.startEditing({
341
+ versionName: "sde.MyEditVersion"
342
+ });
343
+
344
+ // Stop session when done
345
+ await vms.stopEditing({
346
+ sessionId: sessionId,
347
+ saveEdits: true // or false to discard
348
+ });
349
+ ```
350
+
351
+ ### Version Reconcile and Post
352
+
353
+ ```javascript
354
+ // Reconcile version with parent
355
+ const reconcileResult = await vms.reconcile({
356
+ sessionId: sessionId,
357
+ abortIfConflicts: false,
358
+ conflictDetection: "byAttribute", // byAttribute, byObject
359
+ withPost: false,
360
+ conflictResolution: "favorEditVersion" // favorEditVersion, favorTargetVersion
361
+ });
362
+
363
+ console.log("Has conflicts:", reconcileResult.hasConflicts);
364
+ console.log("Conflicts removed:", reconcileResult.conflictsRemoved);
365
+
366
+ if (!reconcileResult.hasConflicts) {
367
+ // Post changes to parent version
368
+ await vms.post({ sessionId });
369
+ console.log("Changes posted successfully");
370
+ }
371
+ ```
372
+
373
+ ### Conflict Detection and Resolution
374
+
375
+ ```javascript
376
+ // Check for conflicts before reconcile
377
+ const conflictResult = await vms.reconcile({
378
+ sessionId: sessionId,
379
+ abortIfConflicts: true, // Stop if conflicts found
380
+ conflictDetection: "byAttribute"
381
+ });
382
+
383
+ if (conflictResult.hasConflicts) {
384
+ // Get conflict details
385
+ console.log("Conflicts found, manual resolution needed");
386
+
387
+ // Resolve conflicts by favoring edit version
388
+ const resolveResult = await vms.reconcile({
389
+ sessionId: sessionId,
390
+ abortIfConflicts: false,
391
+ conflictResolution: "favorEditVersion",
392
+ withPost: true
393
+ });
394
+ }
395
+ ```
396
+
397
+ ### Version Differences
398
+
399
+ ```javascript
400
+ // Get differences between versions
401
+ const differences = await vms.getVersionDifferences({
402
+ sessionId: sessionId,
403
+ fromMoment: "commonAncestor", // commonAncestor, now
404
+ layers: ["0", "1"] // Layer IDs to compare
405
+ });
406
+
407
+ differences.forEach(diff => {
408
+ console.log("Layer:", diff.layerId);
409
+ console.log("Inserts:", diff.inserts);
410
+ console.log("Updates:", diff.updates);
411
+ console.log("Deletes:", diff.deletes);
412
+ });
413
+ ```
414
+
415
+ ### Version Lock Management
416
+
417
+ ```javascript
418
+ // Get lock status
419
+ const lockInfo = await vms.getLockInfo({
420
+ versionName: "sde.MyEditVersion"
421
+ });
422
+
423
+ console.log("Is locked:", lockInfo.isLocked);
424
+ console.log("Locked by:", lockInfo.lockOwner);
425
+ console.log("Lock type:", lockInfo.lockType);
426
+
427
+ // Acquire exclusive lock
428
+ await vms.acquireLock({
429
+ versionName: "sde.MyEditVersion",
430
+ lockType: "exclusive" // shared, exclusive
431
+ });
432
+
433
+ // Release lock
434
+ await vms.releaseLock({
435
+ versionName: "sde.MyEditVersion"
436
+ });
437
+ ```
438
+
439
+ ### Validate Network Topology
440
+
441
+ ```javascript
442
+ // For utility networks - validate topology after edits
443
+ const validateResult = await vms.validateNetworkTopology({
444
+ sessionId: sessionId,
445
+ validateArea: extent, // Optional extent to validate
446
+ validationType: "normal" // normal, rebuild
447
+ });
448
+
449
+ console.log("Validation success:", validateResult.success);
450
+ console.log("Dirty areas remaining:", validateResult.dirtyAreaCount);
451
+ ```
452
+
453
+ ### Complete Version Workflow
454
+
455
+ ```javascript
456
+ async function editInVersion(vms, featureLayer, edits) {
457
+ // 1. Create version
458
+ const version = await vms.createVersion({
459
+ versionName: `Edit_${Date.now()}`,
460
+ description: "Temporary edit version",
461
+ access: "private"
462
+ });
463
+
464
+ try {
465
+ // 2. Switch layer to version
466
+ featureLayer.gdbVersion = version.versionName;
467
+ await featureLayer.refresh();
468
+
469
+ // 3. Start edit session
470
+ const session = await vms.startEditing({
471
+ versionName: version.versionName
472
+ });
473
+
474
+ // 4. Apply edits
475
+ await featureLayer.applyEdits(edits);
476
+
477
+ // 5. Reconcile with parent
478
+ const reconcileResult = await vms.reconcile({
479
+ sessionId: session.sessionId,
480
+ abortIfConflicts: false,
481
+ conflictResolution: "favorEditVersion",
482
+ withPost: false
483
+ });
484
+
485
+ if (reconcileResult.hasConflicts) {
486
+ throw new Error("Conflicts detected during reconcile");
487
+ }
488
+
489
+ // 6. Post to parent
490
+ await vms.post({ sessionId: session.sessionId });
491
+
492
+ // 7. Stop editing
493
+ await vms.stopEditing({
494
+ sessionId: session.sessionId,
495
+ saveEdits: true
496
+ });
497
+
498
+ console.log("Edits posted successfully");
499
+
500
+ } finally {
501
+ // 8. Switch back to default and delete temp version
502
+ featureLayer.gdbVersion = vms.defaultVersionName;
503
+ await featureLayer.refresh();
504
+
505
+ await vms.deleteVersion({
506
+ versionName: version.versionName
507
+ });
508
+ }
509
+ }
510
+ ```
511
+
512
+ ## Related Records
513
+
514
+ ### Query Related Records
515
+ ```javascript
516
+ const relatedRecords = await layer.queryRelatedFeatures({
517
+ outFields: ["*"],
518
+ relationshipId: 0,
519
+ objectIds: [selectedFeature.attributes.OBJECTID]
520
+ });
521
+
522
+ relatedRecords[selectedObjectId].features.forEach(related => {
523
+ console.log("Related:", related.attributes);
524
+ });
525
+ ```
526
+
527
+ ### Edit Related Records in Form
528
+ ```javascript
529
+ const editor = new Editor({
530
+ view: view,
531
+ layerInfos: [{
532
+ layer: parentLayer,
533
+ // Include related tables
534
+ relatedTableInfos: [{
535
+ layer: relatedTable,
536
+ addEnabled: true,
537
+ updateEnabled: true,
538
+ deleteEnabled: true
539
+ }]
540
+ }]
541
+ });
542
+ ```
543
+
544
+ ## Attachments
545
+
546
+ ### Enable Attachments in Editor
547
+ ```javascript
548
+ const editor = new Editor({
549
+ view: view,
550
+ layerInfos: [{
551
+ layer: featureLayer,
552
+ attachmentsOnCreateEnabled: true,
553
+ attachmentsOnUpdateEnabled: true
554
+ }]
555
+ });
556
+ ```
557
+
558
+ ### Programmatic Attachment Handling
559
+ ```javascript
560
+ // Query attachments
561
+ const attachments = await layer.queryAttachments({
562
+ objectIds: [featureOID]
563
+ });
564
+
565
+ // Add attachment
566
+ const formData = new FormData();
567
+ formData.append("attachment", fileBlob, "photo.jpg");
568
+
569
+ await layer.addAttachment(featureOID, formData);
570
+
571
+ // Delete attachment
572
+ await layer.deleteAttachments(featureOID, [attachmentId]);
573
+ ```
574
+
575
+ ## Validation
576
+
577
+ ### Form Validation
578
+ ```javascript
579
+ const form = new FeatureForm({
580
+ layer: featureLayer,
581
+ formTemplate: {
582
+ elements: [{
583
+ type: "field",
584
+ fieldName: "email",
585
+ label: "Email",
586
+ validationExpression: {
587
+ expression: `
588
+ var email = $feature.email;
589
+ return IIf(Find("@", email) > 0, true, { valid: false, errorMessage: "Invalid email" });
590
+ `
591
+ }
592
+ }]
593
+ }
594
+ });
595
+
596
+ // Check validity before submit
597
+ if (form.valid) {
598
+ // Submit
599
+ } else {
600
+ // Show validation errors
601
+ }
602
+ ```
603
+
604
+ ## Complete Example
605
+
606
+ ```html
607
+ <!DOCTYPE html>
608
+ <html>
609
+ <head>
610
+ <link rel="stylesheet" href="https://js.arcgis.com/4.34/esri/themes/light/main.css" />
611
+ <script src="https://js.arcgis.com/4.34/"></script>
612
+ <style>
613
+ html, body, #viewDiv { height: 100%; margin: 0; }
614
+ #formPanel { position: absolute; top: 10px; right: 10px; width: 300px; }
615
+ </style>
616
+ <script type="module">
617
+ import Map from "@arcgis/core/Map.js";
618
+ import MapView from "@arcgis/core/views/MapView.js";
619
+ import FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
620
+ import Editor from "@arcgis/core/widgets/Editor.js";
621
+
622
+ const layer = new FeatureLayer({
623
+ url: "https://services.arcgis.com/.../FeatureServer/0"
624
+ });
625
+
626
+ const map = new Map({
627
+ basemap: "streets-navigation-vector",
628
+ layers: [layer]
629
+ });
630
+
631
+ const view = new MapView({
632
+ container: "viewDiv",
633
+ map: map
634
+ });
635
+
636
+ const editor = new Editor({
637
+ view: view,
638
+ layerInfos: [{
639
+ layer: layer,
640
+ formTemplate: {
641
+ title: "Edit Feature",
642
+ elements: [
643
+ {
644
+ type: "group",
645
+ label: "Details",
646
+ elements: [
647
+ { type: "field", fieldName: "name", label: "Name" },
648
+ { type: "field", fieldName: "type", label: "Type" },
649
+ { type: "field", fieldName: "status", label: "Status" }
650
+ ]
651
+ }
652
+ ]
653
+ },
654
+ attachmentsOnCreateEnabled: true,
655
+ attachmentsOnUpdateEnabled: true
656
+ }]
657
+ });
658
+
659
+ view.ui.add(editor, "top-right");
660
+ </script>
661
+ </head>
662
+ <body>
663
+ <div id="viewDiv"></div>
664
+ </body>
665
+ </html>
666
+ ```
667
+
668
+ ## TypeScript Usage
669
+
670
+ Form elements use autocasting with `type` properties. For TypeScript safety, use `as const`:
671
+
672
+ ```typescript
673
+ // Use 'as const' for type safety in editor configurations
674
+ const editor = new Editor({
675
+ view: view,
676
+ layerInfos: [{
677
+ layer: featureLayer,
678
+ formTemplate: {
679
+ title: "Feature Details",
680
+ elements: [
681
+ { type: "field", fieldName: "name" },
682
+ { type: "field", fieldName: "category" }
683
+ ]
684
+ } as const
685
+ }]
686
+ });
687
+ ```
688
+
689
+ > **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
690
+
691
+ ## Common Pitfalls
692
+
693
+ 1. **Editing permissions**: User must have edit permissions on the layer
694
+
695
+ 2. **Subtype field**: Must match the subtype configuration in the service
696
+
697
+ 3. **Version locking**: Branch versions may lock during editing sessions
698
+
699
+ 4. **Validation expressions**: Must return true/false or error object
700
+
701
+ 5. **Related records**: Require proper relationship configuration in service
702
+