<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>MapImageLayer - dynamic data layer with query table | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
<arcgis-map center="-73.8886, 40.8361" zoom="8">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<calcite-panel slot="top-right">
<calcite-label class="padding-1">
<calcite-select id="layer-select">
<calcite-option value="">All</calcite-option>
<calcite-option value=" WHERE class = 'city'" selected>City</calcite-option>
<calcite-option value=" WHERE class = 'town'">Town</calcite-option>
<calcite-option value=" WHERE class = 'CDP'">Census designated place</calcite-option>
const [Map, MapImageLayer, ClassBreaksRenderer, SimpleMarkerSymbol] = await $arcgis.import([
"@arcgis/core/layers/MapImageLayer.js",
"@arcgis/core/renderers/ClassBreaksRenderer.js",
"@arcgis/core/symbols/SimpleMarkerSymbol.js",
// Reference to the Calcite Select element for choosing a filter or query option.
const layerSelect = document.getElementById("layer-select");
// Define a renderer that styles features by population class breaks.
const renderer = new ClassBreaksRenderer({
symbol: createSymbol("#f8e3c2", 3),
symbol: createSymbol("#e5998c", 6),
symbol: createSymbol("#d86868", 12),
symbol: createSymbol("#9b3557", 22),
// Base SQL query string for the dynamic data layer.
const queryString = "SELECT * FROM ss6.gdb.Places";
// Create a MapImageLayer with a dynamic data sublayer.
// The sublayer uses a SQL query to fetch features from a registered workspace table.
// The query can be updated dynamically based on user selection.
const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
// Indicates the source of the sublayer is a dynamic data layer.
// This object defines the data source of the layer
// in this case it's a table that will be queried
// using a SQL WHERE clause.
workspaceId: "MyDatabaseWorkspaceIDSSR2",
query: queryString + layerSelect.value,
spatialReference: { wkid: 4326 },
// Create a Map instance and add the MapImageLayer.
// Get the map component and assign the map instance.
const viewElement = document.querySelector("arcgis-map");
// Wait for the map view to be ready, then call the updatePlacesSublayer function.
await viewElement?.viewOnReady();
updatePlacesSublayer(layer, layerSelect.value);
// Listen for changes in the Calcite Select and update the sublayer query accordingly.
layerSelect.addEventListener("calciteSelectChange", () => {
updatePlacesSublayer(layer, layerSelect.value);
// Function to create a simple marker symbol with a given color and size.
// Used for rendering features based on their population class.
function createSymbol(color, size) {
return new SimpleMarkerSymbol({
// Function to update the Places sublayer's SQL query based on user selection.
// This function clones the sublayer, updates its query, and reassigns it to the layer.
function updatePlacesSublayer(layer, newValue) {
// Find the "Places" sublayer
const sublayer = layer.sublayers?.find((sublayer) => sublayer.title === "Places");
// Clone the sublayer to avoid mutating the original.
const updatedSublayer = sublayer.clone();
const { dataSource, type } = updatedSublayer.source;
// Update the query if the source is a data-layer with a dataSource.
if (type === "data-layer" && "dataSource" in updatedSublayer.source) {
dataSource.query = queryString + newValue;
// Replace the sublayers array with the updated sublayer.
layer.sublayers = [updatedSublayer];