saschabrunnerch/arcgis-maps-sdk-js-ai-context

arcgis-popup-templates

Configure rich popup content with text, fields, media, charts, attachments, and related records.

查看源码

使用方法

  1. 复制安装命令,在自己的智能体环境安装前先检查源码包。
  2. 从原始文档核对所需工具、凭据和支持的宿主。
  3. 说明输入材料与期望交付物,并对照来源检查输出。
npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-popup-templates

开始前需了解

  • 安装不包含模型订阅、API 额度或访问文件的权限。
  • 仓库星数和安装量反映活跃情况,不等于独立质量或安全测试。
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

ArcGIS Popup Templates

Use this skill for creating and customizing popup templates with various content types.

Import Patterns

Direct ESM Imports

javascript
import PopupTemplate from "@arcgis/core/PopupTemplate.js";
import CustomContent from "@arcgis/core/popup/content/CustomContent.js";

Dynamic Imports (CDN)

javascript
const PopupTemplate = await $arcgis.import("@arcgis/core/PopupTemplate.js");
const CustomContent = await $arcgis.import(
  "@arcgis/core/popup/content/CustomContent.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").

PopupTemplate Overview

Content TypePurpose
TextContentHTML or plain text
FieldsContentAttribute table
MediaContentCharts and images
AttachmentsContentFile attachments
ExpressionContentArcade expression results
CustomContentCustom HTML/JavaScript
RelationshipContentRelated records

PopupTemplate Properties

PropertyTypeDescription
titlestring \Function \objectTitle with field substitution ({fieldName})
contentstring \Array \Function \PromiseContent definition
fieldInfosFieldInfo[]Default field formatting
expressionInfosExpressionInfo[]Arcade expression definitions
outFieldsstring[]Fields to retrieve for popup
actionsActionButton[] \ActionToggle[]Custom action buttons
overwriteActionsbooleanReplace default popup actions
returnGeometrybooleanInclude geometry in popup results

Basic PopupTemplate

javascript
layer.popupTemplate = {
  title: "{name}",
  content: "Population: {population}<br>Area: {area} sq mi",
};

With Field Substitution

javascript
layer.popupTemplate = {
  title: "{city_name}, {state}",
  content: `
    <h3>Demographics</h3>
    <p>Population: {population:NumberFormat(places: 0)}</p>
    <p>Median Income: {median_income:NumberFormat(digitSeparator: true, places: 0)}</p>
    <p>Founded: {founded_date:DateFormat(selector: 'date', datePattern: 'MMMM d, yyyy')}</p>
  `,
};

Content Array (Multiple Content Types)

javascript
layer.popupTemplate = {
  title: "{name}",
  content: [
    {
      type: "text",
      text: "<b>Overview</b><br>{description}",
    },
    {
      type: "fields",
      fieldInfos: [
        { fieldName: "population", label: "Population" },
        { fieldName: "area", label: "Area (sq mi)" },
      ],
    },
    {
      type: "media",
      mediaInfos: [
        {
          type: "pie-chart",
          title: "Demographics",
          value: {
            fields: ["white", "black", "asian", "other"],
          },
        },
      ],
    },
  ],
};

Content Types

TextContent

javascript
{
  type: "text",
  text: `
    <div style="padding: 10px;">
      <h2>{name}</h2>
      <p>{description}</p>
      <a href="{website}" target="_blank">Visit Website</a>
    </div>
  `
}

FieldsContent

javascript
{
  type: "fields",
  fieldInfos: [
    {
      fieldName: "name",
      label: "Name"
    },
    {
      fieldName: "population",
      label: "Population",
      format: {
        digitSeparator: true,
        places: 0
      }
    },
    {
      fieldName: "date_created",
      label: "Created",
      format: {
        dateFormat: "short-date"
      }
    }
  ]
}

Date Formats

  • short-date - 12/30/2024
  • short-date-short-time - 12/30/2024, 3:30 PM
  • short-date-long-time - 12/30/2024, 3:30:45 PM
  • long-month-day-year - December 30, 2024
  • day-short-month-year - 30 Dec 2024
  • year - 2024

MediaContent

javascript
{
  type: "media",
  mediaInfos: [
    {
      title: "Sales by Quarter",
      type: "column-chart",  // bar-chart, pie-chart, line-chart, column-chart, image
      value: {
        fields: ["q1_sales", "q2_sales", "q3_sales", "q4_sales"],
        normalizeField: "total_sales"  // Optional
      }
    }
  ]
}

Chart Types

TypeUse Case
bar-chartHorizontal bars for categorical comparison
pie-chartProportional distribution
line-chartTrends over series
column-chartVertical bars for comparison
imageDisplay images from URL fields

Image MediaInfo:

javascript
{
  type: "image",
  title: "Property Photo",
  value: {
    sourceURL: "{image_url}",
    linkURL: "{detail_page_url}"
  }
}

AttachmentsContent

javascript
{
  type: "attachments",
  displayType: "preview",  // preview, list, auto
  title: "Photos"
}

ExpressionContent

javascript
layer.popupTemplate = {
  expressionInfos: [
    {
      name: "population-density",
      title: "Population Density",
      expression: "Round($feature.population / $feature.area, 2)",
    },
    {
      name: "age-category",
      title: "Age Category",
      expression: `
        var age = $feature.building_age;
        if (age < 25) return "New";
        if (age < 50) return "Moderate";
        return "Historic";
      `,
    },
  ],
  content: [
    {
      type: "expression",
      expressionInfo: {
        name: "population-density",
      },
    },
  ],
};

CustomContent

javascript
import CustomContent from "@arcgis/core/popup/content/CustomContent.js";

const customContent = new CustomContent({
  outFields: ["*"],
  creator: (event) => {
    const div = document.createElement("div");
    const graphic = event.graphic;

    div.innerHTML = `
      <div class="custom-popup">
        <h3>${graphic.attributes.name}</h3>
        <canvas id="chart-${graphic.attributes.OBJECTID}"></canvas>
      </div>
    `;

    return div;
  },
});

layer.popupTemplate = {
  title: "{name}",
  content: [customContent],
};

RelationshipContent

javascript
{
  type: "relationship",
  relationshipId: 0,
  title: "Related Inspections",
  displayCount: 5,
  orderByFields: [
    {
      field: "inspection_date",
      order: "desc"
    }
  ]
}

Popup Component

The <arcgis-popup> component provides popup display control.

Key Properties:

PropertyTypeDescription
actionsCollectionCustom action buttons
contentstring \Node \WidgetPopup content
dock-optionsobjectDocking behavior configuration
featuresGraphic[]Features to display
headingstringPopup heading text
heading-levelnumberHeading level (1-6)
include-default-actions-disabledbooleanDisable default zoom-to action
initial-display-modestringInitial display mode
locationPointPopup anchor location
openbooleanWhether popup is open
selected-featureGraphicCurrently selected feature
selected-feature-indexnumberIndex of selected feature

Key Events:

EventDescription
arcgisTriggerActionFires when a custom action is clicked

Actions

Add custom buttons to popups.

javascript
layer.popupTemplate = {
  title: "{name}",
  content: "...",
  actions: [
    {
      id: "zoom-to",
      title: "Zoom To",
      className: "esri-icon-zoom-in-magnifying-glass",
    },
    {
      id: "edit",
      title: "Edit",
      className: "esri-icon-edit",
    },
  ],
};

// Handle action clicks using reactiveUtils
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";

reactiveUtils.on(
  () => view.popup,
  "trigger-action",
  (event) => {
    if (event.action.id === "zoom-to") {
      view.goTo(view.popup.selectedFeature);
    } else if (event.action.id === "edit") {
      startEditing(view.popup.selectedFeature);
    }
  },
);

Action Button Types

javascript
// Icon button
{ id: "info", title: "More Info", className: "esri-icon-description" }

// Toggle button
{ id: "highlight", title: "Highlight", type: "toggle", value: false }

Dynamic Content with Functions

Content as Function

javascript
layer.popupTemplate = {
  title: "{name}",
  outFields: ["*"],
  content: (feature) => {
    const attributes = feature.graphic.attributes;

    if (attributes.type === "residential") {
      return `
        <h3>Residential Property</h3>
        <p>Bedrooms: ${attributes.bedrooms}</p>
        <p>Bathrooms: ${attributes.bathrooms}</p>
      `;
    } else {
      return `
        <h3>Commercial Property</h3>
        <p>Square Footage: ${attributes.sqft}</p>
      `;
    }
  },
};

Async Content Function

javascript
layer.popupTemplate = {
  title: "{name}",
  outFields: ["*"],
  content: async (feature) => {
    const id = feature.graphic.attributes.OBJECTID;
    const response = await fetch(`/api/details/${id}`);
    const data = await response.json();

    return `
      <h3>${data.title}</h3>
      <p>${data.description}</p>
    `;
  },
};

Arcade Expressions

In Title

javascript
layer.popupTemplate = {
  title: {
    expression: `
      var name = $feature.name;
      var status = $feature.status;
      return name + " (" + status + ")";
    `,
  },
  content: "...",
};

Expression Infos in Fields

javascript
layer.popupTemplate = {
  expressionInfos: [
    {
      name: "formatted-date",
      title: "Formatted Date",
      expression: 'Text($feature.created_date, "MMMM D, YYYY")',
    },
    {
      name: "calculated-field",
      title: "Density",
      expression:
        "Round($feature.population / AreaGeodetic($feature, 'square-miles'), 1)",
    },
  ],
  content: [
    {
      type: "fields",
      fieldInfos: [
        { fieldName: "expression/formatted-date", label: "Created" },
        {
          fieldName: "expression/calculated-field",
          label: "Population Density",
        },
      ],
    },
  ],
};

OutFields

javascript
layer.popupTemplate = {
  title: "{name}",
  content: "...",
  outFields: ["name", "population", "area", "created_date"],
};

// All fields
layer.popupTemplate = {
  title: "{name}",
  content: "...",
  outFields: ["*"],
};

Clustering Popups

javascript
layer.featureReduction = {
  type: "cluster",
  clusterRadius: 80,
  popupTemplate: {
    title: "Cluster of {cluster_count} features",
    content: [
      {
        type: "fields",
        fieldInfos: [
          {
            fieldName: "cluster_count",
            label: "Features in cluster",
          },
          {
            fieldName: "cluster_avg_population",
            label: "Average Population",
            format: { digitSeparator: true, places: 0 },
          },
        ],
      },
    ],
  },
  fields: [
    {
      name: "cluster_avg_population",
      alias: "Average Population",
      onStatisticField: "population",
      statisticType: "avg",
    },
  ],
};

Complete Example: Map Components

html
<!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="gray-vector" center="-73.95,40.70" zoom="11">
      <arcgis-zoom slot="top-left"></arcgis-zoom>
      <arcgis-legend slot="bottom-left"></arcgis-legend>
    </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 template = {
        title: "Marriage in {NAME} Census Tract {TRACT}",
        content: [
          {
            type: "fields",
            fieldInfos: [
              {
                fieldName: "B12001_calc_pctMarriedE",
                label: "Married %",
                format: { digitSeparator: true, places: 1 },
              },
              {
                fieldName: "B12001_calc_pctNeverE",
                label: "Never Married %",
                format: { digitSeparator: true, places: 1 },
              },
            ],
          },
        ],
      };

      const featureLayer = new FeatureLayer({
        url: "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/ACS_Marital_Status_Boundaries/FeatureServer/2",
        popupTemplate: template,
      });
      mapElement.map.add(featureLayer);
    </script>
  </body>
</html>

Reference Samples

  • intro-popuptemplate - Basic PopupTemplate configuration
  • get-started-popuptemplate - Getting started with PopupTemplate
  • popup-actions - Adding custom actions to popups
  • popup-custom-action - Custom popup actions with geometry operators
  • popup-customcontent - Custom popup content elements
  • popuptemplate-arcade - Using Arcade expressions in popups
  • popuptemplate-arcade-expression-content - Arcade expression content
  • popup-multipleelements - Multiple content elements in popups
  • popuptemplate-function - Function-based popup content
  • popuptemplate-promise - Promise-based popup content
  • popuptemplate-browse-related-records - Related records in popups

Common Pitfalls

  1. Field Names Case Sensitive: Field names must match exactly.
javascript
   // If field is "Population" (capital P)
   content: "{Population}"; // Correct
   content: "{population}"; // Wrong - shows literal {population}
  1. OutFields Required: Fields used in popup must be in outFields when using function content.
javascript
   popupTemplate: {
     title: "{name}",
     outFields: ["name", "description"],  // Required for function content
     content: (feature) => {
       return feature.graphic.attributes.description;
     }
   }
  1. Expression Reference: Use expression/ prefix for Arcade expressions in fieldInfos.
javascript
   fieldInfos: [{ fieldName: "expression/my-expression", label: "Calculated" }];
  1. Async Content Must Return: Function content must return a value or Promise.
javascript
   // Wrong - no return
   content: (feature) => {
     const div = document.createElement("div");
   };

   // Correct
   content: (feature) => {
     const div = document.createElement("div");
     return div;
   };
  1. GeoJSON Field Path: GeoJSON requires properties/ prefix for field names.
javascript
   // GeoJSON
   title: "{properties/name}";
   // Regular FeatureLayer
   title: "{name}";

Related Skills

  • See arcgis-interaction for hit testing and event handling.
  • See arcgis-editing for feature editing workflows.
  • See arcgis-arcade for detailed Arcade expression syntax.

按任务相关推荐

来自同一仓库

更多 Skills

全部 Skills