arcgis-tables-forms

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ArcGIS Tables & Forms

ArcGIS 表格与表单

Use this skill for configuring FeatureTable widgets and FormTemplate with various input elements.
本技能用于配置FeatureTable组件和带有各类输入元素的FormTemplate。

FeatureTable

FeatureTable

Display feature attributes in an interactive table.
在交互式表格中展示要素属性。

FeatureTable Component

FeatureTable 组件

html
<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");

  await map.viewOnReady();

  // Set the layer for the table
  const layer = map.view.map.layers.find(l => l.type === "feature");
  table.layer = layer;
</script>
html
<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");

  await map.viewOnReady();

  // Set the layer for the table
  const layer = map.view.map.layers.find(l => l.type === "feature");
  table.layer = layer;
</script>

FeatureTable Widget (Core API)

FeatureTable 组件(核心API)

javascript
import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";

const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv"
});
javascript
import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";

const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv"
});

With Field Configuration

带字段配置

javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  fieldConfigs: [
    {
      name: "name",
      label: "Name",
      direction: "asc"  // Initial sort
    },
    {
      name: "category",
      label: "Category"
    },
    {
      name: "value",
      label: "Value",
      format: {
        digitSeparator: true,
        places: 2
      }
    },
    {
      name: "date_created",
      label: "Created",
      format: {
        dateFormat: "short-date"
      }
    }
  ]
});
javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  fieldConfigs: [
    {
      name: "name",
      label: "Name",
      direction: "asc"  // Initial sort
    },
    {
      name: "category",
      label: "Category"
    },
    {
      name: "value",
      label: "Value",
      format: {
        digitSeparator: true,
        places: 2
      }
    },
    {
      name: "date_created",
      label: "Created",
      format: {
        dateFormat: "short-date"
      }
    }
  ]
});

FeatureTable Configuration

FeatureTable 配置

javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",

  // Display options
  visibleElements: {
    header: true,
    menu: true,
    menuItems: {
      clearSelection: true,
      refreshData: true,
      toggleColumns: true,
      selectedRecordsShowAllToggle: true,
      selectedRecordsShowSelectedToggle: true,
      zoomToSelection: true
    },
    selectionColumn: true,
    columnMenus: true
  },

  // Table behavior
  multiSortEnabled: true,
  editingEnabled: true,
  highlightEnabled: true,
  attachmentsEnabled: true,
  relatedRecordsEnabled: true,

  // Pagination
  pageSize: 50,

  // Initial state
  filterGeometry: view.extent,  // Only show features in view
  highlightOnRowSelectEnabled: true
});
javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",

  // Display options
  visibleElements: {
    header: true,
    menu: true,
    menuItems: {
      clearSelection: true,
      refreshData: true,
      toggleColumns: true,
      selectedRecordsShowAllToggle: true,
      selectedRecordsShowSelectedToggle: true,
      zoomToSelection: true
    },
    selectionColumn: true,
    columnMenus: true
  },

  // Table behavior
  multiSortEnabled: true,
  editingEnabled: true,
  highlightEnabled: true,
  attachmentsEnabled: true,
  relatedRecordsEnabled: true,

  // Pagination
  pageSize: 50,

  // Initial state
  filterGeometry: view.extent,  // Only show features in view
  highlightOnRowSelectEnabled: true
});

Column Templates

列模板

javascript
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",
        sortable: true,
        initialSortPriority: 0,
        direction: "asc"
      }),
      new FieldColumnTemplate({
        fieldName: "status",
        label: "Status",
        menuConfig: {
          items: [{
            label: "Custom Action",
            iconClass: "esri-icon-settings",
            clickFunction: (event) => {
              console.log("Custom action on:", event.feature);
            }
          }]
        }
      }),
      new FieldColumnTemplate({
        fieldName: "value",
        label: "Value ($)",
        textAlign: "right",
        formatFunction: (info) => {
          return `$${info.value.toLocaleString()}`;
        }
      })
    ]
  }
});
javascript
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",
        sortable: true,
        initialSortPriority: 0,
        direction: "asc"
      }),
      new FieldColumnTemplate({
        fieldName: "status",
        label: "Status",
        menuConfig: {
          items: [{
            label: "Custom Action",
            iconClass: "esri-icon-settings",
            clickFunction: (event) => {
              console.log("Custom action on:", event.feature);
            }
          }]
        }
      }),
      new FieldColumnTemplate({
        fieldName: "value",
        label: "Value ($)",
        textAlign: "right",
        formatFunction: (info) => {
          return `$${info.value.toLocaleString()}`;
        }
      })
    ]
  }
});

Group Column Template

分组列模板

javascript
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" })
        ]
      })
    ]
  }
});
javascript
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" })
        ]
      })
    ]
  }
});

FeatureTable Events

FeatureTable 事件

javascript
// Row selection
featureTable.on("selection-change", (event) => {
  console.log("Added:", event.added);
  console.log("Removed:", event.removed);

  // Get all selected features
  const selectedFeatures = featureTable.highlightIds.toArray();
});

// Row click (double-click to zoom)
featureTable.viewModel.on("row-highlight-change", (event) => {
  if (event.feature) {
    view.goTo(event.feature.geometry);
  }
});

// Editing complete
featureTable.on("edit-complete", (event) => {
  console.log("Edited feature:", event.feature);
  console.log("Updated attributes:", event.attributes);
});
javascript
// Row selection
featureTable.on("selection-change", (event) => {
  console.log("Added:", event.added);
  console.log("Removed:", event.removed);

  // Get all selected features
  const selectedFeatures = featureTable.highlightIds.toArray();
});

// Row click (double-click to zoom)
featureTable.viewModel.on("row-highlight-change", (event) => {
  if (event.feature) {
    view.goTo(event.feature.geometry);
  }
});

// Editing complete
featureTable.on("edit-complete", (event) => {
  console.log("Edited feature:", event.feature);
  console.log("Updated attributes:", event.attributes);
});

Programmatic Selection

程序化选择

javascript
// 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);
javascript
// 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);

Filter and Refresh

筛选与刷新

javascript
// 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;
javascript
// 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;

Sync with Map Selection

与地图选择同步

javascript
// Map click selects in table
view.on("click", async (event) => {
  const response = await view.hitTest(event);
  const feature = response.results.find(r => r.layer === featureLayer);

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

// Table selection highlights on map
featureTable.on("selection-change", async (event) => {
  const layerView = await view.whenLayerView(featureLayer);

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

  const objectIds = featureTable.highlightIds.toArray();
  if (objectIds.length > 0) {
    const query = featureLayer.createQuery();
    query.objectIds = objectIds;
    const results = await featureLayer.queryFeatures(query);
    highlightHandle = layerView.highlight(results.features);
  }
});
javascript
// Map click selects in table
view.on("click", async (event) => {
  const response = await view.hitTest(event);
  const feature = response.results.find(r => r.layer === featureLayer);

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

// Table selection highlights on map
featureTable.on("selection-change", async (event) => {
  const layerView = await view.whenLayerView(featureLayer);

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

  const objectIds = featureTable.highlightIds.toArray();
  if (objectIds.length > 0) {
    const query = featureLayer.createQuery();
    query.objectIds = objectIds;
    const results = await featureLayer.queryFeatures(query);
    highlightHandle = layerView.highlight(results.features);
  }
});

FormTemplate

FormTemplate

Configure edit forms for features.
配置要素编辑表单。

Basic FormTemplate

基础FormTemplate

javascript
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;
javascript
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;

Field Elements

字段元素

javascript
import FieldElement from "@arcgis/core/form/elements/FieldElement.js";

const fieldElement = new FieldElement({
  fieldName: "name",
  label: "Name",
  description: "Enter the feature name",
  hint: "Required field",
  requiredExpression: "true",
  editableExpression: "$feature.status != 'locked'",
  visibilityExpression: "$feature.type != 'hidden'"
});
javascript
import FieldElement from "@arcgis/core/form/elements/FieldElement.js";

const fieldElement = new FieldElement({
  fieldName: "name",
  label: "Name",
  description: "Enter the feature name",
  hint: "Required field",
  requiredExpression: "true",
  editableExpression: "$feature.status != 'locked'",
  visibilityExpression: "$feature.type != 'hidden'"
});

Group Elements

分组元素

javascript
import GroupElement from "@arcgis/core/form/elements/GroupElement.js";

const formTemplate = new FormTemplate({
  elements: [
    new GroupElement({
      label: "Basic Information",
      description: "Enter basic details",
      elements: [
        { type: "field", fieldName: "name", label: "Name" },
        { type: "field", fieldName: "type", label: "Type" }
      ]
    }),
    new GroupElement({
      label: "Location",
      initialState: "collapsed",  // expanded, collapsed
      elements: [
        { type: "field", fieldName: "address", label: "Address" },
        { type: "field", fieldName: "city", label: "City" },
        { type: "field", fieldName: "state", label: "State" }
      ]
    })
  ]
});
javascript
import GroupElement from "@arcgis/core/form/elements/GroupElement.js";

const formTemplate = new FormTemplate({
  elements: [
    new GroupElement({
      label: "Basic Information",
      description: "Enter basic details",
      elements: [
        { type: "field", fieldName: "name", label: "Name" },
        { type: "field", fieldName: "type", label: "Type" }
      ]
    }),
    new GroupElement({
      label: "Location",
      initialState: "collapsed",  // expanded, collapsed
      elements: [
        { type: "field", fieldName: "address", label: "Address" },
        { type: "field", fieldName: "city", label: "City" },
        { type: "field", fieldName: "state", label: "State" }
      ]
    })
  ]
});

Text Elements

文本元素

javascript
import TextElement from "@arcgis/core/form/elements/TextElement.js";

const formTemplate = new FormTemplate({
  elements: [
    new TextElement({
      type: "text",
      text: "<h3>Important Instructions</h3><p>Please fill out all required fields.</p>"
    }),
    { type: "field", fieldName: "name", label: "Name" },
    new TextElement({
      text: "<hr><small>Fields below are optional</small>"
    }),
    { type: "field", fieldName: "notes", label: "Notes" }
  ]
});
javascript
import TextElement from "@arcgis/core/form/elements/TextElement.js";

const formTemplate = new FormTemplate({
  elements: [
    new TextElement({
      type: "text",
      text: "<h3>Important Instructions</h3><p>Please fill out all required fields.</p>"
    }),
    { type: "field", fieldName: "name", label: "Name" },
    new TextElement({
      text: "<hr><small>Fields below are optional</small>"
    }),
    { type: "field", fieldName: "notes", label: "Notes" }
  ]
});

Relationship Elements

关联元素

javascript
import RelationshipElement from "@arcgis/core/form/elements/RelationshipElement.js";

const formTemplate = new FormTemplate({
  elements: [
    { type: "field", fieldName: "name", label: "Name" },
    new RelationshipElement({
      relationshipId: 0,
      label: "Related Inspections",
      description: "View and manage related inspection records",
      displayCount: 5,
      orderByFields: [{
        field: "inspection_date",
        order: "desc"
      }],
      editableExpression: "true"
    })
  ]
});
javascript
import RelationshipElement from "@arcgis/core/form/elements/RelationshipElement.js";

const formTemplate = new FormTemplate({
  elements: [
    { type: "field", fieldName: "name", label: "Name" },
    new RelationshipElement({
      relationshipId: 0,
      label: "Related Inspections",
      description: "View and manage related inspection records",
      displayCount: 5,
      orderByFields: [{
        field: "inspection_date",
        order: "desc"
      }],
      editableExpression: "true"
    })
  ]
});

Input Types

输入类型

TextBox Input

文本框输入

javascript
{
  type: "field",
  fieldName: "name",
  label: "Name",
  input: {
    type: "text-box",
    maxLength: 100,
    minLength: 1
  }
}
javascript
{
  type: "field",
  fieldName: "name",
  label: "Name",
  input: {
    type: "text-box",
    maxLength: 100,
    minLength: 1
  }
}

TextArea Input

文本域输入

javascript
{
  type: "field",
  fieldName: "description",
  label: "Description",
  input: {
    type: "text-area",
    maxLength: 1000,
    minLength: 0
  }
}
javascript
{
  type: "field",
  fieldName: "description",
  label: "Description",
  input: {
    type: "text-area",
    maxLength: 1000,
    minLength: 0
  }
}

ComboBox Input

下拉框输入

javascript
{
  type: "field",
  fieldName: "category",
  label: "Category",
  input: {
    type: "combo-box",
    showNoValueOption: true,
    noValueOptionLabel: "Select a category..."
  }
}

// Works with coded value domains
// Domain values automatically populate the combo box
javascript
{
  type: "field",
  fieldName: "category",
  label: "Category",
  input: {
    type: "combo-box",
    showNoValueOption: true,
    noValueOptionLabel: "Select a category..."
  }
}

// Works with coded value domains
// Domain values automatically populate the combo box

Radio Buttons Input

单选按钮输入

javascript
{
  type: "field",
  fieldName: "priority",
  label: "Priority",
  input: {
    type: "radio-buttons",
    showNoValueOption: false
  }
}
javascript
{
  type: "field",
  fieldName: "priority",
  label: "Priority",
  input: {
    type: "radio-buttons",
    showNoValueOption: false
  }
}

Switch Input

开关输入

javascript
{
  type: "field",
  fieldName: "is_active",
  label: "Active",
  input: {
    type: "switch",
    offValue: 0,
    onValue: 1
  }
}
javascript
{
  type: "field",
  fieldName: "is_active",
  label: "Active",
  input: {
    type: "switch",
    offValue: 0,
    onValue: 1
  }
}

DatePicker Input

日期选择器输入

javascript
{
  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
  }
}
javascript
{
  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
  }
}

DateTimePicker Input

日期时间选择器输入

javascript
{
  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
  }
}
javascript
{
  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
  }
}

TimePicker Input

时间选择器输入

javascript
{
  type: "field",
  fieldName: "event_time",
  label: "Event Time",
  input: {
    type: "time-picker"
  }
}
javascript
{
  type: "field",
  fieldName: "event_time",
  label: "Event Time",
  input: {
    type: "time-picker"
  }
}

Barcode Scanner Input

条形码扫描器输入

javascript
{
  type: "field",
  fieldName: "barcode",
  label: "Barcode",
  input: {
    type: "barcode-scanner"
  }
}
javascript
{
  type: "field",
  fieldName: "barcode",
  label: "Barcode",
  input: {
    type: "barcode-scanner"
  }
}

Expression-Based Configuration

基于表达式的配置

Visibility Expressions

可见性表达式

javascript
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" }
      ]
    }
  ]
});
javascript
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" }
      ]
    }
  ]
});

Required Expressions

必填项表达式

javascript
{
  type: "field",
  fieldName: "inspection_notes",
  label: "Inspection Notes",
  requiredExpression: "$feature.inspection_result == 'failed'"
}
javascript
{
  type: "field",
  fieldName: "inspection_notes",
  label: "Inspection Notes",
  requiredExpression: "$feature.inspection_result == 'failed'"
}

Editable Expressions

可编辑表达式

javascript
{
  type: "field",
  fieldName: "approved_by",
  label: "Approved By",
  editableExpression: "$feature.status == 'pending'"
}
javascript
{
  type: "field",
  fieldName: "approved_by",
  label: "Approved By",
  editableExpression: "$feature.status == 'pending'"
}

FeatureForm Widget

FeatureForm 组件

Widget for editing feature attributes.
javascript
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}`);
});
用于编辑要素属性的组件。
javascript
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}`);
});

AttributeTableTemplate

AttributeTableTemplate

Configure attribute table in Editor widget.
javascript
import AttributeTableTemplate from "@arcgis/core/widgets/Editor/support/AttributeTableTemplate.js";
import AttributeTableFieldElement from "@arcgis/core/widgets/Editor/support/AttributeTableFieldElement.js";

const tableTemplate = new AttributeTableTemplate({
  elements: [
    new AttributeTableFieldElement({
      fieldName: "name",
      label: "Name",
      editable: true
    }),
    new AttributeTableFieldElement({
      fieldName: "status",
      label: "Status",
      editable: true
    })
  ]
});
配置Editor组件中的属性表格。
javascript
import AttributeTableTemplate from "@arcgis/core/widgets/Editor/support/AttributeTableTemplate.js";
import AttributeTableFieldElement from "@arcgis/core/widgets/Editor/support/AttributeTableFieldElement.js";

const tableTemplate = new AttributeTableTemplate({
  elements: [
    new AttributeTableFieldElement({
      fieldName: "name",
      label: "Name",
      editable: true
    }),
    new AttributeTableFieldElement({
      fieldName: "status",
      label: "Status",
      editable: true
    })
  ]
});

Editor Widget Integration

Editor 组件集成

javascript
import Editor from "@arcgis/core/widgets/Editor.js";

const editor = new Editor({
  view: view,
  layerInfos: [{
    layer: featureLayer,
    formTemplate: formTemplate,
    enabled: true,
    addEnabled: true,
    updateEnabled: true,
    deleteEnabled: true
  }]
});

view.ui.add(editor, "top-right");
javascript
import Editor from "@arcgis/core/widgets/Editor.js";

const editor = new Editor({
  view: view,
  layerInfos: [{
    layer: featureLayer,
    formTemplate: formTemplate,
    enabled: true,
    addEnabled: true,
    updateEnabled: true,
    deleteEnabled: true
  }]
});

view.ui.add(editor, "top-right");

Common Patterns

常见模式

Complete Form Setup

完整表单设置

javascript
const formTemplate = new FormTemplate({
  title: "Property Information",
  description: "Enter property details",
  preserveFieldValuesWhenHidden: true,
  expressionInfos: [
    {
      name: "is-commercial",
      expression: "$feature.type == 'commercial'"
    }
  ],
  elements: [
    // Header text
    {
      type: "text",
      text: "<b>Basic Information</b>"
    },
    // Required field
    {
      type: "field",
      fieldName: "name",
      label: "Property Name",
      requiredExpression: "true",
      input: { type: "text-box", maxLength: 100 }
    },
    // Dropdown
    {
      type: "field",
      fieldName: "type",
      label: "Property Type",
      input: { type: "combo-box" }
    },
    // Conditional group
    {
      type: "group",
      label: "Commercial Details",
      visibilityExpression: "is-commercial",
      elements: [
        { type: "field", fieldName: "business_type", label: "Business Type" },
        { type: "field", fieldName: "sqft", label: "Square Footage" }
      ]
    },
    // Date field
    {
      type: "field",
      fieldName: "inspection_date",
      label: "Last Inspection",
      input: { type: "date-picker" }
    },
    // Long text
    {
      type: "field",
      fieldName: "notes",
      label: "Notes",
      input: { type: "text-area", maxLength: 500 }
    }
  ]
});
javascript
const formTemplate = new FormTemplate({
  title: "Property Information",
  description: "Enter property details",
  preserveFieldValuesWhenHidden: true,
  expressionInfos: [
    {
      name: "is-commercial",
      expression: "$feature.type == 'commercial'"
    }
  ],
  elements: [
    // Header text
    {
      type: "text",
      text: "<b>Basic Information</b>"
    },
    // Required field
    {
      type: "field",
      fieldName: "name",
      label: "Property Name",
      requiredExpression: "true",
      input: { type: "text-box", maxLength: 100 }
    },
    // Dropdown
    {
      type: "field",
      fieldName: "type",
      label: "Property Type",
      input: { type: "combo-box" }
    },
    // Conditional group
    {
      type: "group",
      label: "Commercial Details",
      visibilityExpression: "is-commercial",
      elements: [
        { type: "field", fieldName: "business_type", label: "Business Type" },
        { type: "field", fieldName: "sqft", label: "Square Footage" }
      ]
    },
    // Date field
    {
      type: "field",
      fieldName: "inspection_date",
      label: "Last Inspection",
      input: { type: "date-picker" }
    },
    // Long text
    {
      type: "field",
      fieldName: "notes",
      label: "Notes",
      input: { type: "text-area", maxLength: 500 }
    }
  ]
});

FeatureTable with Editing

带编辑功能的FeatureTable

javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  editingEnabled: true,
  fieldConfigs: [
    { name: "name", label: "Name", editable: true },
    { name: "status", label: "Status", editable: true },
    { name: "created_date", label: "Created", editable: false }
  ]
});

featureTable.on("edit-complete", async (event) => {
  console.log("Edit saved:", event.feature.attributes);

  // Refresh related data
  await featureLayer.refresh();
});
javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  editingEnabled: true,
  fieldConfigs: [
    { name: "name", label: "Name", editable: true },
    { name: "status", label: "Status", editable: true },
    { name: "created_date", label: "Created", editable: false }
  ]
});

featureTable.on("edit-complete", async (event) => {
  console.log("Edit saved:", event.feature.attributes);

  // Refresh related data
  await featureLayer.refresh();
});

Responsive Table Layout

响应式表格布局

javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  autoRefreshEnabled: true,
  pageSize: 25
});

// Resize handling
window.addEventListener("resize", () => {
  featureTable.refresh();
});

// Toggle visibility
function toggleTable(visible) {
  document.getElementById("tableDiv").style.display = visible ? "block" : "none";
  if (visible) {
    featureTable.refresh();
  }
}
javascript
const featureTable = new FeatureTable({
  view: view,
  layer: featureLayer,
  container: "tableDiv",
  autoRefreshEnabled: true,
  pageSize: 25
});

// Resize handling
window.addEventListener("resize", () => {
  featureTable.refresh();
});

// Toggle visibility
function toggleTable(visible) {
  document.getElementById("tableDiv").style.display = visible ? "block" : "none";
  if (visible) {
    featureTable.refresh();
  }
}

TypeScript Usage

TypeScript 用法

Form elements use autocasting with
type
properties. For TypeScript safety, use
as const
:
typescript
// Use 'as const' for type safety in form templates
const formTemplate = {
  title: "Edit Feature",
  elements: [
    {
      type: "field",
      fieldName: "name",
      label: "Name"
    },
    {
      type: "group",
      label: "Address",
      elements: [
        { type: "field", fieldName: "street" },
        { type: "field", fieldName: "city" }
      ]
    }
  ]
} as const;

// For input types
const formElement = {
  type: "field",
  fieldName: "status",
  input: { type: "combo-box" }
} as const;
Tip: See arcgis-core-maps skill for detailed guidance on autocasting vs explicit classes.
表单元素通过
type
属性自动转换类型。为了TypeScript类型安全,使用
as const
typescript
// Use 'as const' for type safety in form templates
const formTemplate = {
  title: "Edit Feature",
  elements: [
    {
      type: "field",
      fieldName: "name",
      label: "Name"
    },
    {
      type: "group",
      label: "Address",
      elements: [
        { type: "field", fieldName: "street" },
        { type: "field", fieldName: "city" }
      ]
    }
  ]
} as const;

// For input types
const formElement = {
  type: "field",
  fieldName: "status",
  input: { type: "combo-box" }
} as const;
提示: 查看arcgis-core-maps 技能获取关于自动转换类型与显式类的详细指导。

Common Pitfalls

常见陷阱

  1. Field Names Must Match: fieldName must exactly match layer field
    javascript
    // Layer has field "PropertyName"
    { fieldName: "PropertyName" }  // Correct
    { fieldName: "propertyname" }  // Wrong - case sensitive
  2. Coded Value Domains: ComboBox auto-populates from domain
    javascript
    // If field has coded value domain, values come from domain
    { type: "field", fieldName: "status", input: { type: "combo-box" } }
    // Dropdown shows domain values automatically
  3. Expression Names: Reference expressions by name string
    javascript
    expressionInfos: [{ name: "my-expr", expression: "..." }],
    elements: [{
      visibilityExpression: "my-expr"  // String reference
    }]
  4. Layer Must Be Editable: For edit features to work
    javascript
    // Layer capabilities must include editing
    if (layer.capabilities.editing.supportsUpdateByOthers) {
      featureTable.editingEnabled = true;
    }
  5. Container Size: Table needs explicit height
    css
    #tableDiv {
      height: 400px;  /* Required */
      width: 100%;
    }
  1. 字段名称必须匹配:fieldName必须与图层字段完全一致
    javascript
    // Layer has field "PropertyName"
    { fieldName: "PropertyName" }  // Correct
    { fieldName: "propertyname" }  // Wrong - case sensitive
  2. 编码值域:下拉框会自动从值域填充选项
    javascript
    // If field has coded value domain, values come from domain
    { type: "field", fieldName: "status", input: { type: "combo-box" } }
    // Dropdown shows domain values automatically
  3. 表达式名称:通过名称字符串引用表达式
    javascript
    expressionInfos: [{ name: "my-expr", expression: "..." }],
    elements: [{
      visibilityExpression: "my-expr"  // String reference
    }]
  4. 图层必须可编辑:编辑功能才能生效
    javascript
    // Layer capabilities must include editing
    if (layer.capabilities.editing.supportsUpdateByOthers) {
      featureTable.editingEnabled = true;
    }
  5. 容器尺寸:表格需要设置明确高度
    css
    #tableDiv {
      height: 400px;  /* Required */
      width: 100%;
    }