mcpField
A
arcgis-editing

arcgis-editing

github.com/saschabrunnerch開発2347 回インストール29 週間前に更新
リポジトリ

arcgis-editing について

arcgis-editing は、ArcGIS 開発者向けに Editor の設定、フィーチャフォーム、プログラムによる編集、バージョン管理を扱うスキルです。添付ファイル、サブタイプ、関連レコードの操作方法も紹介します。

主な機能

  1. 01Editor とレイヤー編集の設定
  2. 02フィーチャフォームの作成と検証
  3. 03applyEdits によるフィーチャ編集
  4. 04サブタイプとブランチバージョンの管理
  5. 05添付ファイルと関連レコードの検索・処理

活用シーン

  1. 01マップアプリにフィーチャ作成・編集画面を追加
  2. 02レイヤー別に属性・ジオメトリー・添付ファイル編集を設定
  3. 03ブランチバージョンで共同編集
  4. 04コードからフィーチャを追加・更新

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-editing

インストール後、Claude Code で/arcgis-editingを入力して読み込まれたか確認します。

同梱ファイルAGENTS.md

詳細

ArcGIS の編集

Editor の設定、フォームテンプレート、サブタイプ、添付ファイル、バージョニング、プログラムによる編集など、フィーチャを編集する際にこのスキルを使用します。

インポートパターン

直接 ESM インポート
import Editor from "@arcgis/core/widgets/Editor.js";
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";
import FormTemplate from "@arcgis/core/form/FormTemplate.js";
動的インポート(CDN)
const Editor = await $arcgis.import("@arcgis/core/widgets/Editor.js");
const FeatureForm = await $arcgis.import("@arcgis/core/widgets/FeatureForm.js");
const FormTemplate = await $arcgis.import("@arcgis/core/form/FormTemplate.js");

注: このスキルの例では、直接 ESM インポートを使用しています。CDN を使用する場合は、import X from "path" を const X = await $arcgis.import("path") に置き換えてください。

Editor コンポーネント

編集を追加する最も簡単な方法は、<arcgis-editor> コンポーネントを使用することです。

基本的な使い方
<arcgis-map item-id="YOUR_EDITABLE_WEBMAP_ID">
  <arcgis-editor slot="top-right"></arcgis-editor>
</arcgis-map>
主なプロパティ
プロパティ型デフォルト説明
heading-levelnumberアクセシビリティ用の見出しレベル
hide-create-features-sectionbooleanfalseフィーチャ作成パネルを非表示にする
hide-edit-features-sectionbooleanfalseフィーチャ編集パネルを非表示にする
hide-labels-togglebooleanfalseラベルの切り替えを非表示にする
hide-merge-buttonbooleanfalseフィーチャのマージボタンを非表示にする
hide-settings-menubooleanfalse設定メニューを非表示にする
hide-sketchbooleanfalseスケッチツールを非表示にする
hide-split-buttonbooleanfalseフィーチャの分割ボタンを非表示にする
hide-tooltips-togglebooleanfalseツールチップの切り替えを非表示にする
hide-undo-redo-buttonsbooleanfalse元に戻す/やり直しボタンを非表示にする
hide-zoom-to-buttonbooleanfalseズームボタンを非表示にする
labelstringコンポーネントのラベル
layer-infosLayerInfo[]レイヤー編集の設定
snapping-optionsSnappingOptionsスナップの設定
sync-view-selectionbooleanfalseビューと選択内容を同期する
主なイベント
イベント説明
arcgisSketchCreateフィーチャ作成スケッチ中に発生します
arcgisSketchUpdateフィーチャ更新スケッチ中に発生します
arcgisPropertyChangeactiveWorkflow または state が変更されたときに発生します
arcgisReadyコンポーネントの準備が完了したときに発生します
主なメソッド
メソッド説明
cancelWorkflow()アクティブな編集ワークフローをキャンセルします
deleteFeatureFromWorkflow()編集中のフィーチャを削除します
startCreateFeaturesWorkflowAtFeatureTypeSelection()フィーチャの作成を開始します
startUpdateWorkflowAtFeatureEdit(feature)特定のフィーチャの編集を開始します
startUpdateWorkflowAtFeatureSelection()更新するフィーチャの選択を開始します
設定を指定した Editor コンポーネント
<arcgis-map basemap="streets-navigation-vector">
  <arcgis-editor slot="top-right"></arcgis-editor>
</arcgis-map>

<script type="module">
  const FeatureLayer = await $arcgis.import(
    "@arcgis/core/layers/FeatureLayer.js",
  );

  const mapElement = document.querySelector("arcgis-map");
  const view = await mapElement.view;
  await view.when();

  const layer = new FeatureLayer({
    url: "https://services.arcgis.com/.../FeatureServer/0",
  });
  mapElement.map.add(layer);

  const editor = document.querySelector("arcgis-editor");
  editor.layerInfos = [
    {
      layer: layer,
      formTemplate: {
        title: "Edit Feature",
        elements: [
          { type: "field", fieldName: "name", label: "Name" },
          { type: "field", fieldName: "category", label: "Category" },
        ],
      },
      addEnabled: true,
      updateEnabled: true,
      deleteEnabled: false,
    },
  ];
</script>

Editor ウィジェット(Core API)

設定可能な Editor
import Editor from "@arcgis/core/widgets/Editor.js";

const editor = new Editor({
  view: view,
  layerInfos: [
    {
      layer: featureLayer,
      formTemplate: {
        title: "Feature Details",
        description: "Enter feature information",
        elements: [
          {
            type: "field",
            fieldName: "name",
            label: "Name",
            description: "Enter the feature name",
          },
          {
            type: "field",
            fieldName: "category",
            label: "Category",
          },
        ],
      },
      addEnabled: true,
      updateEnabled: true,
      deleteEnabled: false,
    },
  ],
});

view.ui.add(editor, "top-right");
LayerInfo の設定
プロパティ型デフォルト説明
layerFeatureLayer必須編集するレイヤー
formTemplateFormTemplateフォームの設定
enabledbooleantrueレイヤーの編集を有効にする
addEnabledbooleantrueフィーチャの作成を許可する
updateEnabledbooleantrueフィーチャの更新を許可する
deleteEnabledbooleantrueフィーチャの削除を許可する
geometryUpdatesEnabledbooleantrueジオメトリーの編集を許可する
attributeUpdatesEnabledbooleantrue属性の編集を許可する
attachmentsOnCreateEnabledbooleantrue作成時の添付ファイルを許可する
attachmentsOnUpdateEnabledbooleantrue更新時の添付ファイルを許可する

フィーチャフォーム

スタンドアロンのフィーチャフォーム
import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";

const form = new FeatureForm({
  container: "formDiv",
  layer: featureLayer,
  formTemplate: {
    title: "Edit Feature",
    elements: [
      {
        type: "field",
        fieldName: "name",
        label: "Name",
      },
      {
        type: "group",
        label: "Location Details",
        elements: [
          { type: "field", fieldName: "address" },
          { type: "field", fieldName: "city" },
          { type: "field", fieldName: "zip" },
        ],
      },
    ],
  },
});

// Set feature to edit
form.feature = graphic;

// Listen for submit
form.on("submit", async () => {
  if (form.valid) {
    const values = form.getValues();
    graphic.attributes = { ...graphic.attributes, ...values };
    await featureLayer.applyEdits({
      updateFeatures: [graphic],
    });
  }
});
フィーチャフォームコンポーネント
<arcgis-feature-form></arcgis-feature-form>

<script type="module">
  const featureForm = document.querySelector("arcgis-feature-form");

  // Configure the form
  featureForm.formTemplate = {
    title: "Edit Feature",
    elements: [
      { type: "field", fieldName: "name", label: "Name" },
      { type: "field", fieldName: "status", label: "Status" },
    ],
  };

  // Set feature to edit
  featureForm.feature = selectedGraphic;

  // Listen for value changes
  featureForm.addEventListener("arcgisValueChange", (event) => {
    console.log("Field changed:", event.detail.fieldName, event.detail.value);
  });

  // Listen for submit
  featureForm.addEventListener("arcgisSubmit", (event) => {
    console.log("Form submitted");
  });
</script>
グループ化された要素を含むフォーム
const formTemplate = {
  title: "Asset Details",
  elements: [
    {
      type: "group",
      label: "Basic Information",
      elements: [
        { type: "field", fieldName: "asset_id" },
        { type: "field", fieldName: "asset_name" },
        { type: "field", fieldName: "asset_type" },
      ],
    },
    {
      type: "group",
      label: "Maintenance",
      initialState: "collapsed",
      elements: [
        { type: "field", fieldName: "last_inspection" },
        { type: "field", fieldName: "next_inspection" },
        { type: "field", fieldName: "condition" },
      ],
    },
  ],
};
式に基づく表示設定
const formTemplate = {
  expressionInfos: [
    {
      name: "type-requires-subtype",
      expression: "$feature.type == 'complex'",
    },
  ],
  elements: [
    {
      type: "field",
      fieldName: "type",
    },
    {
      type: "field",
      fieldName: "subtype",
      visibilityExpression: "type-requires-subtype",
    },
  ],
};
フォームの検証
const form = new FeatureForm({
  layer: featureLayer,
  formTemplate: {
    elements: [
      {
        type: "field",
        fieldName: "email",
        label: "Email",
        requiredExpression: "email-required",
      },
    ],
    expressionInfos: [
      {
        name: "email-required",
        expression: "$feature.contact_method == 'email'",
      },
    ],
  },
});

// Available expression types on FieldElement:
// - visibilityExpression: controls field visibility
// - editableExpression: controls whether field is editable
// - requiredExpression: controls whether field is required
// - valueExpression: computes a calculated value for the field

if (form.valid) {
  // Submit
}

プログラムによる編集(applyEdits)

// Add features
const addResult = await featureLayer.applyEdits({
  addFeatures: [
    {
      attributes: {
        name: "New Feature",
        category: "Type A",
      },
      geometry: {
        type: "point",
        longitude: -118.805,
        latitude: 34.027,
      },
    },
  ],
});

// Update features
const updateResult = await featureLayer.applyEdits({
  updateFeatures: [
    {
      attributes: {
        OBJECTID: 123,
        name: "Updated Name",
      },
    },
  ],
});

// Delete features
const deleteResult = await featureLayer.applyEdits({
  deleteFeatures: [{ objectId: 123 }],
});

// Check results
addResult.addFeatureResults.forEach((result) => {
  if (result.error) {
    console.error("Add failed:", result.error.message);
  } else {
    console.log("Added feature OID:", result.objectId);
  }
});

サブタイプ

サブタイプの操作
const layer = new FeatureLayer({
  url: "https://services.arcgis.com/.../FeatureServer/0",
});

await layer.load();

const subtypeField = layer.subtypeField;
const subtypes = layer.subtypes;

subtypes.forEach((subtype) => {
  console.log("Code:", subtype.code);
  console.log("Name:", subtype.name);
  console.log("Default values:", subtype.defaultValues);
});
サブタイプグループレイヤー
import SubtypeGroupLayer from "@arcgis/core/layers/SubtypeGroupLayer.js";

const subtypeLayer = new SubtypeGroupLayer({
  url: "https://services.arcgis.com/.../FeatureServer/0",
});

await subtypeLayer.load();

// Access sublayers by subtype
subtypeLayer.sublayers.forEach((sublayer) => {
  console.log("Subtype:", sublayer.subtypeCode, sublayer.title);
  // Each sublayer can have different renderer/popup
});
サブタイプに対応したエディター
const editor = new Editor({
  view: view,
  layerInfos: [
    {
      layer: subtypeGroupLayer,
      addEnabled: true,
      updateEnabled: true,
    },
  ],
});

バージョニング

ブランチバージョニングの概要

ブランチバージョニングでは、調整が行われるまで、複数のユーザーが競合なく同じデータを同時に編集できます。

import VersionManagementService from "@arcgis/core/versionManagement/VersionManagementService.js";

const vms = new VersionManagementService({
  url: "https://services.arcgis.com/.../VersionManagementServer",
});

await vms.load();
console.log("Default version:", vms.defaultVersionIdentifier);
バージョン情報の取得
const versions = await vms.getVersionInfos();
versions.forEach((v) => {
  console.log("Version:", v.versionName);
  console.log("  Owner:", v.versionOwner);
  console.log("  Access:", v.access); // public, protected, private
  console.log("  Parent:", v.parentVersionName);
});
バージョンの作成、変更、削除
// Create new version
const newVersion = await vms.createVersion({
  versionName: "MyEditVersion",
  description: "Version for editing project X",
  access: "private",
  parentVersionName: "sde.DEFAULT",
});

// Alter version properties
await vms.alterVersion({
  versionName: "sde.MyEditVersion",
  description: "Updated description",
  access: "protected",
});

// Delete a version
await vms.deleteVersion({
  versionName: "sde.MyEditVersion",
});
バージョンの切り替え
// Set version on layer at creation
const featureLayer = new FeatureLayer({
  url: "https://services.arcgis.com/.../FeatureServer/0",
  gdbVersion: "sde.MyEditVersion",
});

// Or change version dynamically
await featureLayer.load();
featureLayer.gdbVersion = "sde.AnotherVersion";
await featureLayer.refresh();
編集セッションと調整
const versionIdentifier = version.versionIdentifier;

// Start editing session
await vms.startEditing({ versionIdentifier });

// Apply edits to feature layer
await featureLayer.applyEdits(edits);

// Reconcile with parent
const reconcileResult = await vms.reconcile({
  versionIdentifier: versionIdentifier,
  abortIfConflicts: false,
  conflictDetection: "by-attribute",
  conflictResolution: "favorEditVersion",
  withPost: false,
});

if (!reconcileResult.hasConflicts) {
  await vms.post({ versionIdentifier });
}

// Stop editing
await vms.stopEditing({
  versionIdentifier: versionIdentifier,
  saveEdits: true,
});
バージョン管理の全ワークフロー
async function editInVersion(vms, featureLayer, edits) {
  const version = await vms.createVersion({
    versionName: `Edit_${Date.now()}`,
    description: "Temporary edit version",
    access: "private",
  });

  const versionIdentifier = version.versionIdentifier;

  try {
    featureLayer.gdbVersion = version.versionName;
    await featureLayer.refresh();

    await vms.startEditing({ versionIdentifier });
    await featureLayer.applyEdits(edits);

    const result = await vms.reconcile({
      versionIdentifier,
      abortIfConflicts: false,
      conflictResolution: "favorEditVersion",
      withPost: false,
    });

    if (result.hasConflicts) {
      throw new Error("Conflicts detected during reconcile");
    }

    await vms.post({ versionIdentifier });
    await vms.stopEditing({ versionIdentifier, saveEdits: true });
  } finally {
    featureLayer.gdbVersion = vms.defaultVersionIdentifier;
    await featureLayer.refresh();
    await vms.deleteVersion({ versionName: version.versionName });
  }
}

関連レコード

関連レコードのクエリ
const relatedRecords = await layer.queryRelatedFeatures({
  outFields: ["*"],
  relationshipId: 0,
  objectIds: [selectedFeature.attributes.OBJECTID],
});

const results = relatedRecords[selectedFeature.attributes.OBJECTID];
results.features.forEach((related) => {
  console.log("Related:", related.attributes);
});

添付ファイル

エディターで添付ファイルを有効にする
const editor = new Editor({
  view: view,
  layerInfos: [
    {
      layer: featureLayer,
      attachmentsOnCreateEnabled: true,
      attachmentsOnUpdateEnabled: true,
    },
  ],
});
プログラムによる添付ファイルの処理
// Query attachments
const attachments = await layer.queryAttachments({
  objectIds: [featureOID],
});

// Add attachment
const formData = new FormData();
formData.append("attachment", fileBlob, "photo.jpg");
await layer.addAttachment(featureOID, formData);

// Delete attachment
await layer.deleteAttachments(featureOID, [attachmentId]);

完全な例:マップコンポーネント

<!DOCTYPE html>
<html>
  <head>
    <script src="https://js.arcgis.com/5.0/"></script>
    <script
      type="module"
      src="https://js.arcgis.com/5.0/map-components/"
    ></script>
    <style>
      html,
      body {
        height: 100%;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <arcgis-map
      basemap="streets-navigation-vector"
      center="-118.805,34.027"
      zoom="13"
    >
      <arcgis-zoom slot="top-left"></arcgis-zoom>
      <arcgis-editor slot="top-right"></arcgis-editor>
    </arcgis-map>

    <script type="module">
      const FeatureLayer = await $arcgis.import(
        "@arcgis/core/layers/FeatureLayer.js",
      );

      const mapElement = document.querySelector("arcgis-map");
      const view = await mapElement.view;
      await view.when();

      const layer = new FeatureLayer({
        url: "https://services.arcgis.com/.../FeatureServer/0",
      });
      mapElement.map.add(layer);

      const editor = document.querySelector("arcgis-editor");
      editor.layerInfos = [
        {
          layer: layer,
          formTemplate: {
            title: "Edit Feature",
            elements: [
              {
                type: "group",
                label: "Details",
                elements: [
                  { type: "field", fieldName: "name", label: "Name" },
                  { type: "field", fieldName: "type", label: "Type" },
                  { type: "field", fieldName: "status", label: "Status" },
                ],
              },
            ],
          },
          attachmentsOnCreateEnabled: true,
          attachmentsOnUpdateEnabled: true,
        },
      ];
    </script>
  </body>
</html>

参考サンプル

  • editor-basic - エディターコンポーネントの基本的な使用方法
  • widgets-editor-configurable - layerInfos を使用した設定可能なエディターウィジェット
  • widgets-editor-subtypes - サブタイプグループレイヤーを使用した編集
  • widgets-editor-form-elements - エディターのフォーム要素の設定
  • editing-applyedits - applyEdits を使用したプログラムによる編集
  • editing-groupedfeatureform - グループ化されたフィーチャフォームのレイアウト
  • editing-featureform-fieldvisibility - フィールドの表示設定
  • changing-version - ジオデータベースのバージョンの切り替え

よくある落とし穴

  1. 編集権限:編集機能を確認せずにレイヤーで applyEdits を呼び出すと、エラーが通知されないまま失敗します。

    // Anti-pattern: calling applyEdits without checking capabilities
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0",
    });
    await layer.applyEdits({ addFeatures: [newFeature] });
    
    // Correct: check capabilities before editing
    const layer = new FeatureLayer({
      url: "https://services.arcgis.com/.../FeatureServer/0",
    });
    await layer.load();
    if (
      layer.editingEnabled &&
      layer.capabilities?.editing?.supportsAddingFeatures
    ) {
      await layer.applyEdits({ addFeatures: [newFeature] });
    } else {
      console.error("Layer does not support adding features");
    }
    

    影響: applyEdits の呼び出しは、判別しにくいサーバーエラーで失敗するか、見落としやすいエラー結果を通知なしで返します。

  2. バージョンロック:適切なセッション管理をせずにブランチバージョニングされたデータを編集すると、バージョンロックが発生します。

    // Anti-pattern: editing without version management session
    layer.gdbVersion = "editor1.design_v1";
    await layer.applyEdits({ updateFeatures: [updatedFeature] });
    // Version remains locked, blocking other users
    
    // Correct: use proper version management session
    await vms.startEditing({ versionIdentifier });
    layer.gdbVersion = "editor1.design_v1";
    await layer.applyEdits({ updateFeatures: [updatedFeature] });
    await vms.stopEditing({ versionIdentifier, saveEdits: true });
    

    影響: 編集後もバージョンがロックされたままとなり、他のユーザーがアクセスしたり編集したりできなくなります。

  3. applyEdits の結果確認:個々のフィーチャのエラーを確認するため、必ず結果オブジェクトを調べてください。

    const result = await layer.applyEdits({ addFeatures: [feature1, feature2] });
    result.addFeatureResults.forEach((res) => {
      if (res.error) {
        console.error("Failed to add feature:", res.error.message);
      }
    });
    
  4. フォーム式の名前:式のテキストではなく、名前の文字列で式を参照する必要があります。

    expressionInfos: [{ name: "my-expr", expression: "$feature.type == 'A'" }],
    elements: [{
      visibilityExpression: "my-expr"  // String reference to name
    }]
    
  5. サブタイプフィールド:サービスのサブタイプ設定と完全に一致している必要があります。

関連スキル

  • FeatureTable と FormTemplate の入力型については、arcgis-tables-forms を参照してください。
  • ヒットテストとスケッチについては、arcgis-interaction を参照してください。
  • FeatureLayer の設定については、arcgis-layers を参照してください。
  • オートキャストのガイダンスについては、arcgis-core-maps を参照してください。

コメント