<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
  <title>FeatureTable widget with a map | Sample | ArcGIS API for JavaScript 4.18</title>

  <link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.18/"></script>

  <style>
    html,
    body {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }

    #viewDiv {
      height: 50%;
      width: 100%;
    }

    #zoom {
      margin-bottom: 5px;
    }

    #actions {
      padding: 5px;
    }

    .container,
		#tableDiv,
		#tableDiv2 {
      height: 50%;
      width: 100%;
    }

  </style>
</head>

<body>
  <div id="viewDiv"></div>
  <div class="container">
    <div id="tableDiv"></div>
		<div id="tableDiv2"></div>
  </div>
  <div id="actions" class="esri-widget">
    <button class="esri-button" id="zoom">Zoom to selected feature(s)</button>
    <button class="esri-button" id="fullextent">Full extent</button>
		<button class="esri-button" id="newTable">New Table</button>
  </div>
</body>

</html>
import WebMap from "https://js.arcgis.com/4.19/@arcgis/core/WebMap.js";
import MapView from "https://js.arcgis.com/4.19/@arcgis/core/views/MapView.js";
import FeatureLayer from "https://js.arcgis.com/4.19/@arcgis/core/layers/FeatureLayer.js";
import FeatureTable from "https://js.arcgis.com/4.19/@arcgis/core/widgets/FeatureTable.js";

const features = [];
const webmap = new WebMap({
	portalItem: {
		id: "3c245fe893234d4f85e4edaa41a9e0bf"
	}
});

let view = new MapView({
	container: "viewDiv",
	map: webmap,
	popup: {
		autoOpenEnabled: false
	} //disable popups
});

function createLayer(lyr, title, source) {
	const tempLayer = new FeatureLayer({
		title,
		fields: lyr.fields.map((x) => x.clone()),
		geometryType: lyr.geometryType,
		renderer: lyr.renderer.clone(),
		spatialReference: lyr.spatialReference.clone(),
		source,
		visible: false
	});
	return tempLayer;
}

view.when(function () {
	const featureLayer = webmap.layers.getItemAt(0); //grabs the first layer in the map
	featureLayer.title = "USFS Recreational areas";

	// Create the feature table
	const featureTable = new FeatureTable({
		view: view, // required for feature highlight to work
		layer: featureLayer,
		// Autocast the FieldColumnConfigs
		fieldConfigs: [
			{
				name: "RECAREANAM",
				label: "Recreation area name",
				direction: "asc"
			},
			{
				name: "FORESTNAME",
				label: "Forest name"
			},
			{
				name: "OPENSTATUS",
				label: "Open status"
			},
			{
				name: "OPEN_SEASO",
				label: "Season begins"
			},
			{
				name: "RECAREADES",
				label: "Recreation description"
			},
			{
				name: "RESTRICTIO",
				label: "Restrictions"
			}
		],
		container: document.getElementById("tableDiv")
	});

	// Add buttons to the mapView
	view.ui.add(document.getElementById("actions"), "top-right");

	// Listen for the table's selection-change event
	featureTable.on("selection-change", function (changes) {
		// If the selection is removed, remove the feature from the array
		changes.removed.forEach(function (item) {
			const data = features.find(function (data) {
				return data.feature === item.feature;
			});
			if (data) {
				features.splice(features.indexOf(data), 1);
			}
		});

		// If the selection is added, push all added selections to array
		changes.added.forEach(function (item) {
			const feature = item.feature;
			features.push({
				feature: feature
			});
		});
	});

	// Listen for the click on the view and select any associated row in the table
	view.on("immediate-click", function (event) {
		view.hitTest(event).then(function (response) {
			const candidate = response.results.find(function (result) {
				return (
					result.graphic &&
					result.graphic.layer &&
					result.graphic.layer === featureLayer
				);
			});
			// Select the rows of the clicked feature
			candidate && featureTable.selectRows(candidate.graphic);
		});
	});

	const zoomBtn = document.getElementById("zoom");
	const fullExtentBtn = document.getElementById("fullextent");
	const btnTable = document.getElementById("newTable");

	// Wire up button click event listeners
	zoomBtn.addEventListener("click", zoomToSelectedFeature);
	fullExtentBtn.addEventListener("click", fullExtent);
	btnTable.addEventListener("click", () => {
		// do something here
		const source = features.map((x) => x.feature);
		const layer = createLayer(featureLayer, "Copy Layer", source);
		const fTable = new FeatureTable({
			view: view, // required for feature highlight to work
			layer: layer,
			// Autocast the FieldColumnConfigs
			fieldConfigs: [
				{
					name: "RECAREANAM",
					label: "Recreation area name",
					direction: "asc"
				},
				{
					name: "FORESTNAME",
					label: "Forest name"
				},
				{
					name: "OPENSTATUS",
					label: "Open status"
				},
				{
					name: "OPEN_SEASO",
					label: "Season begins"
				},
				{
					name: "RECAREADES",
					label: "Recreation description"
				},
				{
					name: "RESTRICTIO",
					label: "Restrictions"
				}
			],
			container: document.getElementById("tableDiv2")
		});
	});

	// fires when "Zoom to selected feature(s)" button is clicked
	function zoomToSelectedFeature() {
		// Create a query off of the feature layer
		const query = featureLayer.createQuery();
		// Iterate through the features and grab the feature's objectID
		const featureIds = features.map(function (result) {
			return result.feature.getAttribute(featureLayer.objectIdField);
		});
		// Set the query's objectId
		query.objectIds = featureIds;
		// Make sure to return the geometry to zoom to
		query.returnGeometry = true;
		// Call queryFeatures on the feature layer and zoom to the resulting features
		featureLayer.queryFeatures(query).then(function (results) {
			view.goTo(results.features).catch(function (error) {
				if (error.name != "AbortError") {
					console.error(error);
				}
			});
		});
	}
	// Fires when "Full extent" button is clicked
	function fullExtent() {
		// Zooms to the full extent of the feature layer
		view.goTo(featureLayer.fullExtent).catch(function (error) {
			if (error.name != "AbortError") {
				console.error(error);
			}
		});
	}
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.