# Arcgis Tables Forms

> Configure FeatureTable for tabular data display and FormTemplate with input elements for feature editing forms. Use when adding spreadsheet-style data grids, building attribute edit forms, configuring form input types and validation, or surfacing related records in forms.

- **Type:** Skill
- **Install:** `agentstack add skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-tables-forms`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [SaschaBrunnerCH](https://agentstack.voostack.com/s/saschabrunnerch)
- **Installs:** 0
- **Category:** [Data & Analytics](https://agentstack.voostack.com/c/data-and-analytics)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [SaschaBrunnerCH](https://github.com/SaschaBrunnerCH)
- **Source:** https://github.com/SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context/tree/master/skills/arcgis-tables-forms

## Install

```sh
agentstack add skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-tables-forms
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# ArcGIS Tables & Forms

Use this skill for configuring FeatureTable components/widgets and FormTemplate with various input elements.

## Import Patterns

### Direct ESM Imports

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

### Dynamic Imports (CDN)

```javascript
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",
);
```

> **Note:** The examples in this skill use Direct ESM imports. For CDN usage, replace `import X from "path"` with `const X = await $arcgis.import("path")`.

## FeatureTable Component

### Basic Usage

```html

  

  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;

```

### Key Properties

| Property                      | Type                   | Default | Description                      |
| ----------------------------- | ---------------------- | ------- | -------------------------------- |
| `layer`                       | FeatureLayer           |         | The layer to display             |
| `attribute-table-template`    | AttributeTableTemplate |         | Table configuration (new in 5.0) |
| `editing-enabled`             | boolean                | false   | Enable inline editing            |
| `filter-by-selection-enabled` | boolean                | false   | Filter by selected features      |
| `highlight-disabled`          | boolean                | false   | Disable row highlighting         |
| `hide-header`                 | boolean                | false   | Hide the table header            |
| `hide-menu`                   | boolean                | false   | Hide the table menu              |
| `hide-selection-column`       | boolean                | false   | Hide the selection column        |
| `multiple-selection-disabled` | boolean                | false   | Disable multi-row selection      |
| `multiple-sort-enabled`       | boolean                | false   | Enable multi-column sorting      |
| `page-size`                   | number                 |         | Rows per page                    |
| `auto-save-disabled`          | boolean                | false   | Disable auto-saving edits        |
| `definition-expression`       | string                 |         | Filter expression                |
| `time-zone`                   | string                 |         | Time zone for dates              |

#### Hide Menu Items

| Property                                  | Description                      |
| ----------------------------------------- | -------------------------------- |
| `hide-menu-items-clear-selection`         | Hide clear selection menu item   |
| `hide-menu-items-delete-selection`        | Hide delete selection menu item  |
| `hide-menu-items-export-selection-to-csv` | Hide export to CSV menu item     |
| `hide-menu-items-refresh-data`            | Hide refresh data menu item      |
| `hide-menu-items-toggle-columns`          | Hide toggle columns menu item    |
| `hide-menu-items-zoom-to-selection`       | Hide zoom to selection menu item |

### Key Events

| Event                   | Description                             |
| ----------------------- | --------------------------------------- |
| `arcgisSelectionChange` | Fires when row selection changes        |
| `arcgisCellClick`       | Fires when a cell is clicked            |
| `arcgisCellKeydown`     | Fires on keyboard interaction in a cell |
| `arcgisCellPointerover` | Fires when pointer enters a cell        |
| `arcgisCellPointerout`  | Fires when pointer leaves a cell        |
| `arcgisColumnReorder`   | Fires when columns are reordered        |
| `arcgisPropertyChange`  | Fires when a property changes           |
| `arcgisReady`           | Fires when the component is ready       |

### Component with Configuration

```html

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

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

```

## FeatureTable Widget (Core API)

### Basic Widget

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

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

### Configured Widget

```javascript
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,
});
```

### 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",
        initialSortPriority: 0,
        direction: "asc",
      }),
      new FieldColumnTemplate({
        fieldName: "status",
        label: "Status",
      }),
      new FieldColumnTemplate({
        fieldName: "value",
        label: "Value ($)",
        textAlign: "right",
      }),
    ],
  },
});
```

#### FieldColumnTemplate Properties

| Property              | Type    | Description            |
| --------------------- | ------- | ---------------------- |
| `fieldName`           | string  | Field to display       |
| `label`               | string  | Column header text     |
| `editable`            | boolean | Allow editing          |
| `visible`             | boolean | Column visibility      |
| `frozen`              | boolean | Freeze column to left  |
| `frozenToEnd`         | boolean | Freeze column to right |
| `resizable`           | boolean | Allow column resizing  |
| `autoWidth`           | boolean | Auto-size column width |
| `width`               | number  | Column width in pixels |
| `textAlign`           | string  | Text alignment         |
| `textWrap`            | boolean | Wrap text in cells     |
| `initialSortPriority` | number  | Sort priority          |

### 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" }),
        ],
      }),
    ],
  },
});
```

## AttributeTableTemplate (New in 5.0)

Configure table display using `AttributeTableTemplate`, which can be set on a layer or on the feature table component.

```javascript
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 Element Types

| Type           | Class                             | Description             |
| -------------- | --------------------------------- | ----------------------- |
| `field`        | AttributeTableFieldElement        | Individual field column |
| `group`        | AttributeTableGroupElement        | Group of columns        |
| `relationship` | AttributeTableRelationshipElement | Related records         |
| `attachment`   | AttributeTableAttachmentElement   | Attachment column       |

## Selection and Highlighting

### 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);
```

### Watch Selection Changes

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

### 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.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 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;
```

## FormTemplate

Configure edit forms for features.

### Basic 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;
```

### FormTemplate Properties

| Property                        | Type             | Description                   |
| ------------------------------- | ---------------- | ----------------------------- |
| `title`                         | string           | Form title                    |
| `description`                   | string           | Form description              |
| `elements`                      | FormElement[]    | Array of form elements        |
| `expressionInfos`               | ExpressionInfo[] | Arcade expression definitions |
| `preserveFieldValuesWhenHidden` | boolean          | Keep hidden field values      |

### Form Element Types

| Type           | Description                            |
| -------------- | -------------------------------------- |
| `field`        | FieldElement - Edit a specific field   |
| `group`        | GroupElement - Group of elements       |
| `text`         | TextElement - Static text/HTML content |
| `relationship` | RelationshipElement - Related records  |
| `attachment`   | AttachmentElement - File attachments   |

### Field Elements

```javascript
{
  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'"
}
```

### Group Elements

```javascript
{
  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" }
  ]
}
```

### Text Elements

```javascript
{
  type: "text",
  text: "Important InstructionsPlease fill out all required fields."
}
```

### Relationship Elements

```javascript
{
  type: "relationship",
  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
  }
}
```

### TextArea Input

```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 - values auto-populate from domain
```

### Radio Buttons Input

```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
  }
}
```

### 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
  }
}
```

### 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
  }
}
```

### TimePicker Input

```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"
  }
}
```

## 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 == 'resid

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [SaschaBrunnerCH](https://github.com/SaschaBrunnerCH)
- **Source:** [SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context](https://github.com/SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-tables-forms
- Seller: https://agentstack.voostack.com/s/saschabrunnerch
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
