The Have two filters that will allow a user to chose a major command or grade. However, can someone point me into the right direction on how to actually have them listen to each other. for example, if the user pics a 30ABCT and wants to filter that by the grade of E4. What is the way I need to do that?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>
MOS Status - Test
</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,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#grade-filter{
height: 315px;
width: 150%;
visibility: hidden;
}
.grade-item {
width: 100%;
padding: 12px;
text-align: center;
vertical-align: baseline;
cursor: pointer;
height: 40px;
}
.grade-item:focus {
background-color: dimgrey;
}
.grade-item:hover {
background-color: dimgrey;
}
#major-command-filter{
height: 315px;
width: 150%;
visibility: hidden;
}
.majorCommand-item {
width: 100%;
padding: 12px;
text-align: center;
vertical-align: baseline;
cursor: pointer;
height: 40px;
}
.majorCommand-item:focus {
background-color: dimgrey;
}
.majorCommand-item:hover {
background-color: dimgrey;
}
.esri-editor .esri-item-list__scroller {
max-height: 350px;
}
#info {
padding: 14px;
border-radius: 5px;
width: 25%;
}
</style>
<script>
require([
"esri/Map",
"esri/layers/FeatureLayer",
"esri/form/FormTemplate",
"esri/widgets/Editor",
"esri/views/MapView",
"esri/widgets/Expand",
"esri/popup/content/TextContent",
], function (
Map,
FeatureLayer,
FormTemplate,
Editor,
MapView,
Expand,
TextContent,
) {
const editThisAction = {
title: "Edit feature",
id: "edit-this",
className: "esri-icon-edit",
};
let editor, features, majorCommandView, gradeView;
// Create a popTemplate
const template = {
title: "MOS Vacancy: {mos}",
content:
"<ul><li>Grade: <b>{grade}</b></li>" +
"<li>Unit: <b>{unit}</b></li>" +
"<li>Major Command: <b>{macom}</b></li>" +
"<li>City: <b>{city}</b></li><ul>",
actions: [editThisAction],
};
// Create a map from the referenced webmap item id
const featureLayer = new FeatureLayer({
url:
"https://ncguardview.nc.gov/server/rest/services/Hosted/test/FeatureServer/0",
outFields: ["*"],
displayField: "mos",
popupTemplate: template,
formTemplate: {
title: "NCNG MOS Vacancy",
description: "Provide information for MOS Vacancy",
elements: [
{
// Autocasts to new GroupElement
type: "group",
label: "Military Occupation Specaility",
//description: "Field inspector information",
elements: [
{
// Autocasts to new FieldElement
type: "field",
fieldName: "mos",
label: "MOS",
},
{
type: "field",
fieldName: "series",
label: "MOS Branch",
},
{
type: "field",
fieldName: "jobtitle",
label: "MOS Job Title",
},
{
type: "field",
fieldName: "grade",
label: "MOS Grade",
},
],
}, // end of first group element
{
type: "group",
label: "Unit",
elements: [
{
type: "field",
fieldName: "unit",
label: "Unit",
},
{
type: "field",
fieldName: "battalion",
label: "Battalion",
},
{
type: "field",
fieldName: "macom",
label: "Major Command",
},
],
}, // End of Second Group
{
type: "group",
label: "Location",
elements: [
{
type: "field",
fieldName: "address",
label: "Unit Address",
},
{
type: "field",
fieldName: "city",
label: "Unit City",
},
{
type: "field",
fieldName: "county",
label: "Unit County",
},
],
}, // End of Second Group,
{
type: "group",
label: "Status",
elements:[{
type: "field",
fieldName: "vacancy",
label: "Vacancy Status",
}]
}
],
},
});
// Create the Map
const map = new Map({
basemap: "streets-night-vector",
layers: [featureLayer]
});
//map.add(featureLayer);
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 6,
center: [-79, 35],
});
///////////////////////////////////////////////////////////////////
/* Grade Filter */
// Doesn't really filter out Grade. The filter still inlcudes
// whatever grades are at that location
const gradeNode = document.querySelectorAll(`.grade-item`);
const gradeElement = document.getElementById("grade-filter");
gradeElement.addEventListener('click', filterByGrade); // handle user choice
// Handle selection for user filter
function filterByGrade(event) {
const selectedGrade = event.target.getAttribute("data-grade");
gradeView.filter = {
where: "grade = '"+ selectedGrade +"'",
};
};
view.whenLayerView(featureLayer).then(function (layerView) {
gradeView = layerView;
// set up UI items
gradeElement.style.visibility = 'visible';
const gradeExpand = new Expand({
view: view,
content: gradeElement,
expandIconClass: "esri-icon-filter",
group: "top-left",
});
// clear filters
gradeExpand.watch("expanded", function(){
if(!gradeExpand.expanded) {
gradeView.filter = null;
};
});
view.ui.add(gradeExpand, 'top-left');
});
///////////////////////////////////////////////////////////////////
const majComNode = document.querySelectorAll(`.majorCommand-item`);
const majComElement = document.getElementById("major-command-filter");
// click event handler for seasons choices
majComElement.addEventListener("click", filterByCommand);
// User clicked on Major Commands 30th, 449th, 13th, and etc..
// set an attribute filter on major command layer view
function filterByCommand(event) {
const selectedCommand = event.target.getAttribute("data-command");
majorCommandView.filter = {
where: "macom = '" + selectedCommand + "'",
};
}
view.whenLayerView(featureLayer).then(function (layerView) {
majorCommandView = layerView;
// set up UI items
majComElement.style.visibility = "visible";
const majCommandExpand = new Expand({
view: view,
content: majComElement,
expandIconClass: "esri-icon-filter",
group: "top-left",
});
// clear the filters
majCommandExpand.watch( "expanded", function() {
if(!majCommandExpand.expanded) {
majorCommandView.filter = null;
}
});
view.ui.add(majCommandExpand, 'top-left')
//////////////////////////////////////////
/* Stop with Filter and Begin with Editor */
/////////////////////////////////////////////////////
view.when(function () {
view.popup.autoOpenEnabled = true; //disable popups
// Create the Editor
let editor = new Editor({
view: view,
container: document.createElement("div"),
layerInfos: [
{
layer: featureLayer,
deleteEnabled: true,
addEnabled: true,
},
],
});
// Add widget to top-right of the view
//view.ui.add(editor, "bottom-right");
// Execute each time the "Edit Feature" action is called
function editThis() {
// If the EditorViewModel's activeWorkflow is null, make the popup not visible
if (!editor.viewModel.activeWorkFlow) {
view.popup.visible =false;
editor.startUpdateWorkflowAtFeatureEdit(
view.popup.selectedFeature
);
view.ui.add(editor, "bottom-right");
view.popup.spinnerEnabled = true;
}
// We need to set a timeout to ensure the editor widget is fully rendered. We
// then grab it from the DOM stack
setTimeout(function () {
// Use the editor's back button as a way to cancel out of editing
let arrComp = editor.domNode.getElementsByClassName(
"esri-editor__back-button esri-interactive"
);
if (arrComp.length === 1) {
// Add a tooltip for the back button
arrComp[0].setAttribute(
"title",
"Cancel edits, return to popup"
);
// Add a listerner to listen for when the editor's back button is clicked
arrComp[0].addEventListener("click", function (evt) {
console.log(evt);
// Prevent the default behavior for the back button and instead remove the editor and reopen the popup
evt.preventDefault();
//view.ui.remove(editor);
view.popup.open({
features: features,
});
});
}
}, 150);
}
// Event handler that fires each time an action is clicked
view.popup.on("trigger-action", function (event) {
if (event.action.id === "edit-this") {
editThis();
}
});
// Watch when the popup is visible
view.popup.watch("visible", function (event) {
// Check the Editor's viewModel state, if it is currently open and editing existing features, disable popups
if (editor.viewModel.state === "editing-existing-feature") {
view.popup.close();
} else {
// Grab the features of the popup
features = view.popup.features;
}
});
featureLayer.on("apply-edits", function () {
// Once edits are applied to the layer, remove the Editor from the UI
//view.ui.remove(editor);
// Iterate through the features
features.forEach(function (feature) {
// Reset the template for the feature if it was edited
feature.popupTemplate = template;
});
// Open the popup again and reset its content after updates were made on the feature
if (features) {
view.popup.open({
features: features,
});
}
// Cancel the workflow so that once edits are applied, a new popup can be displayed
editor.viewModel.cancelWorkflow();
});
});
});
view.ui.add("info", {
position: "bottom-left",
index: 1,
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="major-command-filter" class="esri-widget">
<div class="majorCommand-item visible-command" data-command="30 ABCT">30 ABCT</div>
<div class="majorCommand-item visible-command" data-command="130 MEB">130 MEB</div>
<div class="majorCommand-item visible-command" data-command="113 SB">113 SB</div>
<div class="majorCommand-item visible-command" data-command="60 TC">60 TC</div>
<div class="majorCommand-item visible-command" data-command="449 TAB">449 TAB</div>
<div class="majorCommand-item visible-command" data-command="139 REG">139 REG</div>
<div class="majorCommand-item visible-command" data-command="JFHQ">JFHQ</div>
<div class="majorCommand-item visible-command" data-command="TEST">TEST</div>
</dvi>
<div id="grade-filter" class="esri-widget">
<div class="grade-item visible-grade" data-grade="E1">E1</div>
<div class="grade-item visible-grade" data-grade="E2">E2</div>
<div class="grade-item visible-grade" data-grade="E3">E3</div>
<div class="grade-item visible-grade" data-grade="E4">E4</div>
<div class="grade-item visible-grade" data-grade="E5">E5</div>
<div class="grade-item visible-grade" data-grade="E6">E6</div>
<div class="grade-item visible-grade" data-grade="E7">E7</div>
<div class="grade-item visible-grade" data-grade="E8">E8</div>
</dvi>
<div id="info" class="esri-widget">
<h3>Select a feature to display its popup</h3>
<h4>
Edit the feature by clicking on the "Edit feature" action within the
popup.
</h4>
</div>
</body>
</html>
You had the right idea, just a couple of things:
Take a look at the code I made for you, base on your code but simplify to just the filter logic.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>
MOS Status - Test
</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,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#grade-filter {
height: 315px;
width: 150%;
}
.grade-item {
width: 100%;
padding: 12px;
text-align: center;
vertical-align: baseline;
cursor: pointer;
height: 40px;
}
.grade-item:focus {
background-color: dimgrey;
}
.grade-item:hover {
background-color: dimgrey;
}
#major-command-filter {
height: 315px;
width: 150%;
}
.majorCommand-item {
width: 100%;
padding: 12px;
text-align: center;
vertical-align: baseline;
cursor: pointer;
height: 40px;
}
.majorCommand-item:focus {
background-color: dimgrey;
}
.majorCommand-item:hover {
background-color: dimgrey;
}
</style>
<script>
require([
"esri/Map",
"esri/layers/FeatureLayer",
"esri/views/MapView",
"esri/widgets/Expand"
], function (
Map,
FeatureLayer,
MapView,
Expand
) {
// map & layer set up
const featureLayer = new FeatureLayer({
url: "https://ncguardview.nc.gov/server/rest/services/Hosted/test/FeatureServer/0",
outFields: ["*"]
});
const map = new Map({
basemap: "streets-night-vector",
layers: [featureLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 6,
center: [-79, 35],
});
let flView = null;
view.whenLayerView(featureLayer).then(layerView => flView = layerView);
// filter logic
let selectedGrade = null;
let selectedCommand = null;
const updateFilter = function() {
let conditions = [];
if (selectedGrade) {
conditions.push(`(grade='${selectedGrade}')`);
}
if (selectedCommand) {
conditions.push(`(macom='${selectedCommand}')`);
}
flView.filter = conditions.length > 0 ? {where: conditions.join("AND")} : null;
console.log(flView.filter && flView.filter.where);
}
// click event handlers
const filterByGrade = (event) => {
selectedGrade = event.target.getAttribute("data-grade");
updateFilter();
}
const filterByCommand = (event) => {
selectedCommand = event.target.getAttribute("data-command");
updateFilter();
}
// grade ui set up
const gradeElement = document.getElementById("grade-filter");
const gradeExpand = new Expand({
view: view,
content: gradeElement,
expandIconClass: "esri-icon-filter",
// group: "top-left",
});
gradeExpand.watch("expanded", expanded => {
if (!expanded) {
selectedGrade = null;
updateFilter();
}
});
view.ui.add(gradeExpand, 'top-left');
// major command ui set up
const majComElement = document.getElementById("major-command-filter");
const majCommandExpand = new Expand({
view: view,
content: majComElement,
expandIconClass: "esri-icon-filter",
// group: "top-left",
});
majCommandExpand.watch("expanded", expanded => {
if (!expanded) {
selectedCommand = null;
updateFilter();
}
});
view.ui.add(majCommandExpand, 'top-left');
// listen click events
gradeElement.addEventListener('click', filterByGrade);
majComElement.addEventListener("click", filterByCommand);
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="major-command-filter" class="esri-widget">
<div class="majorCommand-item visible-command" data-command="30 ABCT">30 ABCT</div>
<div class="majorCommand-item visible-command" data-command="130 MEB">130 MEB</div>
<div class="majorCommand-item visible-command" data-command="113 SB">113 SB</div>
<div class="majorCommand-item visible-command" data-command="60 TC">60 TC</div>
<div class="majorCommand-item visible-command" data-command="449 TAB">449 TAB</div>
<div class="majorCommand-item visible-command" data-command="139 REG">139 REG</div>
<div class="majorCommand-item visible-command" data-command="JFHQ">JFHQ</div>
<div class="majorCommand-item visible-command" data-command="TEST">TEST</div>
</div>
<div id="grade-filter" class="esri-widget">
<div class="grade-item visible-grade" data-grade="E1">E1</div>
<div class="grade-item visible-grade" data-grade="E2">E2</div>
<div class="grade-item visible-grade" data-grade="E3">E3</div>
<div class="grade-item visible-grade" data-grade="E4">E4</div>
<div class="grade-item visible-grade" data-grade="E5">E5</div>
<div class="grade-item visible-grade" data-grade="E6">E6</div>
<div class="grade-item visible-grade" data-grade="E7">E7</div>
<div class="grade-item visible-grade" data-grade="E8">E8</div>
</div>
</body>
</html>