@saschabrunnerch/arcgis-maps-sdk-js-ai-context 0.0.2 → 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 -203
- 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/{claude → skills}/arcgis-starter-app-extended/SKILL.md +649 -649
- 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 +19 -104
- 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-starter-app-extended.instructions.md +0 -643
- package/contexts/4.34/copilot/arcgis-starter-app.instructions.md +0 -268
- 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
- /package/contexts/4.34/{claude → skills}/arcgis-starter-app/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
|
+
|