mcpField
A
arcgis-tables-forms

arcgis-tables-forms

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

arcgis-tables-forms について

ArcGIS Maps SDK for JavaScriptでフィーチャーテーブルや属性編集フォームを作る開発者向けのスキルです。テーブル設定、選択、列構成、フォーム入力、式による動作制御を解説します。

主な機能

  1. 01FeatureTable の列と表示の設定
  2. 02レコードのインライン編集と選択管理
  3. 03多様な入力形式によるフォーム作成
  4. 04フィールドのグループ化と関連レコード表示
  5. 05式による表示制御と検証

活用シーン

  1. 01レイヤー用の編集可能な属性テーブル作成
  2. 02構造化されたフィーチャー編集フォームの設計
  3. 03テーブル選択とマップ上のフィーチャーの同期

インストール

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

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

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

詳細

ArcGIS テーブルとフォーム

FeatureTable コンポーネント/ウィジェットや、さまざまな入力要素を含む FormTemplate を設定する場合に、このスキルを使用します。

インポートパターン

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

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

FeatureTable コンポーネント

基本的な使い方
<arcgis-map item-id="YOUR_WEBMAP_ID">
  <arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>

<arcgis-feature-table reference-element="arcgis-map"></arcgis-feature-table>

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

  const view = await map.view;
  await view.when();

  const layer = view.map.layers.find((l) => l.type === "feature");
  table.layer = layer;
</script>
主なプロパティ
プロパティ型デフォルト説明
layerFeatureLayer表示するレイヤー
attribute-table-templateAttributeTableTemplateテーブルの設定(5.0 で追加)
editing-enabledbooleanfalseインライン編集を有効にする
filter-by-selection-enabledbooleanfalse選択したフィーチャでフィルターする
highlight-disabledbooleanfalse行のハイライトを無効にする
hide-headerbooleanfalseテーブルヘッダーを非表示にする
hide-menubooleanfalseテーブルメニューを非表示にする
hide-selection-columnbooleanfalse選択列を非表示にする
multiple-selection-disabledbooleanfalse複数行の選択を無効にする
multiple-sort-enabledbooleanfalse複数列の並べ替えを有効にする
page-sizenumber1 ページあたりの行数
auto-save-disabledbooleanfalse編集内容の自動保存を無効にする
definition-expressionstringフィルター式
time-zonestring日付のタイムゾーン
メニュー項目を非表示にする
プロパティ説明
hide-menu-items-clear-selection選択解除のメニュー項目を非表示にする
hide-menu-items-delete-selection選択削除のメニュー項目を非表示にする
hide-menu-items-export-selection-to-csvCSV にエクスポートするメニュー項目を非表示にする
hide-menu-items-refresh-dataデータ更新のメニュー項目を非表示にする
hide-menu-items-toggle-columns列の切り替えメニュー項目を非表示にする
hide-menu-items-zoom-to-selection選択範囲にズームするメニュー項目を非表示にする
主なイベント
イベント説明
arcgisSelectionChange行の選択が変更されたときに発生します
arcgisCellClickセルがクリックされたときに発生します
arcgisCellKeydownセルでキーボード操作が行われたときに発生します
arcgisCellPointeroverポインターがセルに入ったときに発生します
arcgisCellPointeroutポインターがセルから出たときに発生します
arcgisColumnReorder列の順序が変更されたときに発生します
arcgisPropertyChangeプロパティが変更されたときに発生します
arcgisReadyコンポーネントの準備ができたときに発生します
設定を使用したコンポーネント
<arcgis-feature-table
  reference-element="arcgis-map"
  editing-enabled
  multiple-sort-enabled
  page-size="50"
  hide-menu-items-delete-selection
></arcgis-feature-table>

<script type="module">
  const table = document.querySelector("arcgis-feature-table");
  table.layer = featureLayer;

  table.addEventListener("arcgisSelectionChange", (event) => {
    console.log("Selection changed");
  });
</script>

FeatureTable ウィジェット(Core API)

基本的なウィジェット
import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";

const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
});
設定済みのウィジェット
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  editingEnabled: true,
  multiSortEnabled: true,
  highlightEnabled: true,
  attachmentsEnabled: true,
  relatedRecordsEnabled: true,
  pageSize: 50,
  filterGeometry: view.extent,
});
列テンプレート
import FieldColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/FieldColumnTemplate.js";

const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  tableTemplate: {
    columnTemplates: [
      new FieldColumnTemplate({
        fieldName: "name",
        label: "Name",
        initialSortPriority: 0,
        direction: "asc",
      }),
      new FieldColumnTemplate({
        fieldName: "status",
        label: "Status",
      }),
      new FieldColumnTemplate({
        fieldName: "value",
        label: "Value ($)",
        textAlign: "right",
      }),
    ],
  },
});
FieldColumnTemplate のプロパティ
プロパティ型説明
fieldNamestring表示するフィールド
labelstring列ヘッダーのテキスト
editableboolean編集を許可する
visibleboolean列の表示状態
frozenboolean列を左側に固定
frozenToEndboolean列を右側に固定
resizableboolean列のサイズ変更を許可する
autoWidthboolean列幅を自動調整する
widthnumber列幅(ピクセル単位)
textAlignstringテキストの配置
textWrapbooleanセル内のテキストを折り返す
initialSortPrioritynumber初期の並べ替え優先度
グループ列テンプレート
import GroupColumnTemplate from "@arcgis/core/widgets/FeatureTable/support/GroupColumnTemplate.js";

const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  tableTemplate: {
    columnTemplates: [
      new GroupColumnTemplate({
        label: "Location",
        columnTemplates: [
          new FieldColumnTemplate({ fieldName: "city", label: "City" }),
          new FieldColumnTemplate({ fieldName: "state", label: "State" }),
          new FieldColumnTemplate({ fieldName: "country", label: "Country" }),
        ],
      }),
      new GroupColumnTemplate({
        label: "Details",
        columnTemplates: [
          new FieldColumnTemplate({ fieldName: "name", label: "Name" }),
          new FieldColumnTemplate({ fieldName: "type", label: "Type" }),
        ],
      }),
    ],
  },
});

AttributeTableTemplate(5.0 で新登場)

AttributeTableTemplate を使用してテーブルの表示を設定します。レイヤーまたはフィーチャテーブルコンポーネントに設定できます。

import AttributeTableTemplate from "@arcgis/core/tables/AttributeTableTemplate.js";

const tableTemplate = new AttributeTableTemplate({
  elements: [
    {
      type: "field",
      fieldName: "name",
      label: "Name",
    },
    {
      type: "field",
      fieldName: "status",
      label: "Status",
    },
    {
      type: "group",
      label: "Location",
      elements: [
        { type: "field", fieldName: "city", label: "City" },
        { type: "field", fieldName: "state", label: "State" },
      ],
    },
  ],
  orderByFields: [{ field: "name", order: "asc" }],
});

// Set on the feature table component
const table = document.querySelector("arcgis-feature-table");
table.attributeTableTemplate = tableTemplate;

// Or set on the layer
featureLayer.attributeTableTemplate = tableTemplate;
AttributeTableTemplate の要素タイプ
タイプクラス説明
fieldAttributeTableFieldElement個別のフィールド列
groupAttributeTableGroupElement列のグループ
relationshipAttributeTableRelationshipElement関連レコード
attachmentAttributeTableAttachmentElement添付ファイル列

選択とハイライト表示

プログラムによる選択
// Select by ObjectIDs
featureTable.highlightIds.add(123);
featureTable.highlightIds.addMany([124, 125, 126]);

// Clear selection
featureTable.highlightIds.removeAll();

// Select from query
const results = await featureLayer.queryObjectIds({
  where: "status = 'active'",
});
featureTable.highlightIds.addMany(results);
選択の変更を監視する
featureTable.highlightIds.on("change", (event) => {
  console.log("Added IDs:", event.added);
  console.log("Removed IDs:", event.removed);

  const selectedIds = featureTable.highlightIds.toArray();
  console.log("All selected:", selectedIds);
});
マップの選択と同期する
// Map click selects in table
view.on("click", async (event) => {
  const response = await view.hitTest(event);
  const feature = response.results.find(
    (r) => r.graphic.layer === featureLayer,
  );

  if (feature) {
    featureTable.highlightIds.removeAll();
    featureTable.highlightIds.add(feature.graphic.attributes.OBJECTID);
  }
});

// Table selection highlights on map
let highlightHandle;

featureTable.highlightIds.on("change", async () => {
  const layerView = await view.whenLayerView(featureLayer);

  if (highlightHandle) {
    highlightHandle.remove();
  }

  const objectIds = featureTable.highlightIds.toArray();
  if (objectIds.length > 0) {
    highlightHandle = layerView.highlight(objectIds);
  }
});
フィルターと更新
// Filter by geometry
featureTable.filterGeometry = view.extent;

// Filter by expression
featureTable.layer.definitionExpression = "category = 'A'";

// Refresh data
featureTable.refresh();

// Clear filters
featureTable.filterGeometry = null;
featureTable.layer.definitionExpression = null;

FormTemplate

フィーチャの編集フォームを設定します。

基本的な FormTemplate
import FormTemplate from "@arcgis/core/form/FormTemplate.js";

const formTemplate = new FormTemplate({
  title: "Edit Feature",
  description: "Update the feature attributes",
  elements: [
    {
      type: "field",
      fieldName: "name",
      label: "Name",
    },
    {
      type: "field",
      fieldName: "category",
      label: "Category",
    },
    {
      type: "field",
      fieldName: "description",
      label: "Description",
    },
  ],
});

featureLayer.formTemplate = formTemplate;
FormTemplate のプロパティ
プロパティ型説明
titlestringフォームのタイトル
descriptionstringフォームの説明
elementsFormElement[]フォーム要素の配列
expressionInfosExpressionInfo[]Arcade 式の定義
preserveFieldValuesWhenHiddenboolean非表示のフィールド値を保持する
フォーム要素のタイプ
タイプ説明
fieldFieldElement - 特定のフィールドを編集する
groupGroupElement - 要素のグループ
textTextElement - 静的なテキスト/HTML コンテンツ
relationshipRelationshipElement - 関連レコード
attachmentAttachmentElement - ファイル添付
フィールド要素
{
  type: "field",
  fieldName: "name",
  label: "Name",
  description: "Enter the feature name",
  hint: "Required field",
  requiredExpression: "always-required",
  editableExpression: "$feature.status != 'locked'",
  visibilityExpression: "$feature.type != 'hidden'"
}
グループ要素
{
  type: "group",
  label: "Location",
  description: "Address information",
  initialState: "collapsed",  // expanded, collapsed
  elements: [
    { type: "field", fieldName: "address", label: "Address" },
    { type: "field", fieldName: "city", label: "City" },
    { type: "field", fieldName: "state", label: "State" }
  ]
}
テキスト要素
{
  type: "text",
  text: "<h3>Important Instructions</h3><p>Please fill out all required fields.</p>"
}
リレーションシップ要素
{
  type: "relationship",
  relationshipId: 0,
  label: "Related Inspections",
  description: "View and manage related inspection records",
  displayCount: 5,
  orderByFields: [{
    field: "inspection_date",
    order: "desc"
  }],
  editableExpression: "true"
}

入力タイプ

テキストボックス入力
{
  type: "field",
  fieldName: "name",
  label: "Name",
  input: {
    type: "text-box",
    maxLength: 100,
    minLength: 1
  }
}
テキストエリア入力
{
  type: "field",
  fieldName: "description",
  label: "Description",
  input: {
    type: "text-area",
    maxLength: 1000,
    minLength: 0
  }
}
コンボボックス入力
{
  type: "field",
  fieldName: "category",
  label: "Category",
  input: {
    type: "combo-box",
    showNoValueOption: true,
    noValueOptionLabel: "Select a category..."
  }
}
// Works with coded value domains - values auto-populate from domain
ラジオボタン入力
{
  type: "field",
  fieldName: "priority",
  label: "Priority",
  input: {
    type: "radio-buttons",
    showNoValueOption: false
  }
}
スイッチ入力
{
  type: "field",
  fieldName: "is_active",
  label: "Active",
  input: {
    type: "switch",
    offValue: 0,
    onValue: 1
  }
}
日付ピッカー入力
{
  type: "field",
  fieldName: "start_date",
  label: "Start Date",
  input: {
    type: "date-picker",
    min: new Date("2020-01-01"),
    max: new Date("2030-12-31"),
    includeTime: false
  }
}
日時ピッカー入力
{
  type: "field",
  fieldName: "event_datetime",
  label: "Event Date/Time",
  input: {
    type: "datetime-picker",
    min: new Date("2020-01-01T00:00:00"),
    max: new Date("2030-12-31T23:59:59"),
    includeTime: true
  }
}
時刻ピッカー入力
{
  type: "field",
  fieldName: "event_time",
  label: "Event Time",
  input: {
    type: "time-picker"
  }
}
バーコードスキャナー入力
{
  type: "field",
  fieldName: "barcode",
  label: "Barcode",
  input: {
    type: "barcode-scanner"
  }
}

式に基づく設定

表示式
const formTemplate = new FormTemplate({
  expressionInfos: [
    {
      name: "show-commercial-fields",
      expression: "$feature.property_type == 'commercial'",
    },
    {
      name: "show-residential-fields",
      expression: "$feature.property_type == 'residential'",
    },
  ],
  elements: [
    { type: "field", fieldName: "property_type", label: "Property Type" },
    {
      type: "group",
      label: "Commercial Details",
      visibilityExpression: "show-commercial-fields",
      elements: [
        { type: "field", fieldName: "business_name", label: "Business Name" },
        { type: "field", fieldName: "num_employees", label: "Employees" },
      ],
    },
    {
      type: "group",
      label: "Residential Details",
      visibilityExpression: "show-residential-fields",
      elements: [
        { type: "field", fieldName: "num_bedrooms", label: "Bedrooms" },
        { type: "field", fieldName: "num_bathrooms", label: "Bathrooms" },
      ],
    },
  ],
});
必須および編集可能の式
// Conditionally required
{
  type: "field",
  fieldName: "inspection_notes",
  label: "Inspection Notes",
  requiredExpression: "notes-required"
}

// Conditionally editable
{
  type: "field",
  fieldName: "approved_by",
  label: "Approved By",
  editableExpression: "is-pending"
}

FeatureForm ウィジェット

import FeatureForm from "@arcgis/core/widgets/FeatureForm.js";

const featureForm = new FeatureForm({
  container: "formDiv",
  layer: featureLayer,
  formTemplate: formTemplate,
});

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

// Listen for submit
featureForm.on("submit", () => {
  if (featureForm.feature) {
    const updated = featureForm.getValues();

    featureLayer.applyEdits({
      updateFeatures: [
        {
          attributes: {
            ...featureForm.feature.attributes,
            ...updated,
          },
          geometry: featureForm.feature.geometry,
        },
      ],
    });
  }
});

// Handle value changes
featureForm.on("value-change", (event) => {
  console.log(`${event.fieldName} changed to ${event.value}`);
});

完全な例:マップを含む FeatureTable

<!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;
      }
      #container {
        display: flex;
        flex-direction: column;
        height: 100%;
      }
      arcgis-map {
        flex: 1;
      }
      #tableDiv {
        height: 300px;
      }
    </style>
  </head>
  <body>
    <div id="container">
      <arcgis-map
        basemap="streets-navigation-vector"
        center="-118.805,34.027"
        zoom="11"
      >
        <arcgis-zoom slot="top-left"></arcgis-zoom>
      </arcgis-map>
      <arcgis-feature-table
        reference-element="arcgis-map"
        editing-enabled
      ></arcgis-feature-table>
    </div>

    <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 featureLayer = new FeatureLayer({
        url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0",
      });
      mapElement.map.add(featureLayer);

      const table = document.querySelector("arcgis-feature-table");
      table.layer = featureLayer;

      // Highlight table selection on map
      let highlightHandle;

      table.addEventListener("arcgisSelectionChange", async () => {
        const layerView = await view.whenLayerView(featureLayer);

        if (highlightHandle) {
          highlightHandle.remove();
        }

        const objectIds = table.highlightIds?.toArray();
        if (objectIds && objectIds.length > 0) {
          highlightHandle = layerView.highlight(objectIds);
        }
      });
    </script>
  </body>
</html>

完全な例:Editor を含む FormTemplate

<!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: "Property Information",
            description: "Enter property details",
            preserveFieldValuesWhenHidden: true,
            expressionInfos: [
              {
                name: "is-commercial",
                expression: "$feature.type == 'commercial'",
              },
            ],
            elements: [
              {
                type: "field",
                fieldName: "name",
                label: "Property Name",
                input: { type: "text-box", maxLength: 100 },
              },
              {
                type: "field",
                fieldName: "type",
                label: "Property Type",
                input: { type: "combo-box" },
              },
              {
                type: "group",
                label: "Commercial Details",
                visibilityExpression: "is-commercial",
                elements: [
                  {
                    type: "field",
                    fieldName: "business_type",
                    label: "Business Type",
                  },
                  { type: "field", fieldName: "sqft", label: "Square Footage" },
                ],
              },
              {
                type: "field",
                fieldName: "inspection_date",
                label: "Last Inspection",
                input: { type: "date-picker" },
              },
              {
                type: "field",
                fieldName: "notes",
                label: "Notes",
                input: { type: "text-area", maxLength: 500 },
              },
            ],
          },
        },
      ];
    </script>
  </body>
</html>

参考サンプル

  • feature-table - FeatureTable コンポーネントの使用方法
  • widgets-featuretable-editing - FeatureTable を使った編集
  • widgets-featuretable-map - FeatureTable とマップの統合
  • widgets-featuretable-relates - 関連レコードを含む FeatureTable
  • editing-groupedfeatureform - グループ化されたフィーチャフォームのレイアウト
  • editing-featureform-fieldvisibility - フォームでのフィールドの表示制御

よくある落とし穴

  1. フィールド名は一致している必要があります:fieldName はレイヤーのフィールド名と完全に一致する必要があります(大文字と小文字を区別します)。

    // Layer has field "PropertyName"
    {
      fieldName: "PropertyName";
    } // Correct
    {
      fieldName: "propertyname";
    } // Wrong - case sensitive
    
  2. コード値ドメイン:ComboBox はドメイン値から自動的に項目を追加します。

    // If field has coded value domain, values come from domain
    { type: "field", fieldName: "status", input: { type: "combo-box" } }
    // Dropdown shows domain values automatically - no manual options needed
    
  3. 式の名前:式のテキストではなく、名前文字列で式を参照します。

    expressionInfos: [{ name: "my-expr", expression: "..." }],
    elements: [{
      visibilityExpression: "my-expr"  // String reference to name
    }]
    
  4. レイヤーは編集可能である必要があります:編集を有効にする前に、機能を確認してください。

    await layer.load();
    if (layer.capabilities?.editing?.supportsUpdateByOthers) {
      featureTable.editingEnabled = true;
    }
    
  5. コンテナーのサイズ:FeatureTable ウィジェットのコンテナーには、高さを明示的に設定する必要があります。

    #tableDiv {
      height: 400px; /* Required - table won't render without explicit height */
      width: 100%;
    }
    
  6. ハイライト ID の型:highlightIds には文字列ではなく、ObjectID の数値を指定します。

    featureTable.highlightIds.add(123); // Correct - number
    featureTable.highlightIds.add("123"); // Wrong - string
    

関連スキル

  • Editor の構成、applyEdits、バージョン管理については、arcgis-editing を参照してください。
  • PopupTemplate の構成については、arcgis-popup-templates を参照してください。
  • ヒットテストとマップの選択については、arcgis-interaction を参照してください。
  • FeatureLayer の構成については、arcgis-layers を参照してください。

コメント