Query widget based on click

3522
4
Jump to solution
01-21-2016 11:11 AM
BradJones
New Contributor III

I'm putting together a web app in WAB Developer.  it is 95% complete but the last 5% is important. I need a widget that will query a work-order table based on a the user clicking on a feature.  There is no spatial info in the work-order table.  So it will be on the two relating fields between data sets (upstream manhole, downstream manhole).  This limits using relationships, which appears to not be supported in WAB anyway.

I'm starting to learn JS and GIS web dev, but it's a long haul to building my own widgets.  Any ideas?

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Brad,

  This is not WAB widget code but the below is a JS sample that allows for related records query that you may be able to use as a starting point:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Test for domain fields in related table</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.15/dijit/themes/claro/claro.css" />
    <link rel="stylesheet" href="https://js.arcgis.com/3.15/esri/css/esri.css" />
    <style>
        html, body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
            margin: 0;
            font-family: "Open Sans";
        }
        #leftPane {
            width: 20%;
            margin: 0;
            border: none;
        }
        #map {
            padding: 0;
        }
    </style>
    <script src="https://js.arcgis.com/3.15/"></script>
    <script>
        require([
            "dojo/ready",
            "dojo/on",
            "dojo/_base/lang",
            'esri/tasks/RelationshipQuery',
            "dojo/dom",
            "dijit/registry",
            "dojo/dom-construct",
            "dojo/parser",
            "esri/map",
            "esri/arcgis/utils",
            "esri/domUtils",
            "esri/dijit/Popup",
            "esri/dijit/PopupTemplate",
            "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane"
        ], function (
            ready, on, lang, RelationshipQuery, dom, registry, domConstruct, parser, Map,
            arcgisUtils, domUtils, Popup, PopupTemplate, BorderContainer, ContentPane
        ) {
            ready(function () {

                parser.parse();
                //Create a map based on an ArcGIS Online web map id
                arcgisUtils.createMap("ba61bf1495494336ba347b3286389cd8", "map").then(function (response) {
                    window.map = response.map;
                    this.selectedLayer = map.getLayer(response.itemInfo.itemData.operationalLayers[0].id);
                    this.data = response.itemInfo.itemData.tables[0];
                    //set the popup's popupWindow property to false. This prevents the popup from displaying
                    map.infoWindow.set("popupWinow", false);
                    initializeSidebar(window.map);
                }, function (error) {
                    console.log("Map creation failed: ", dojo.toJson(error));
                });

                function initializeSidebar(map) {
                    var popup = map.infoWindow;

                    //when the selection changes update the side panel to display the popup info for the
                    //currently selected feature.
                    on(popup, "selection-change", function () {
                        displayPopupContent(popup.getSelectedFeature());
                    });

                    //when the selection is cleared remove the popup content from the side panel.
                    on(popup, "clear-features", function () {
                        dom.byId("featureCount").innerHTML = "Click to select feature(s)";
                        registry.byId("leftPane").set("content", "");
                        domUtils.hide(dom.byId("pager"));
                    });

                    //When features are associated with the  map's info window update the sidebar with the new content.
                    on(popup, "set-features", function () {
                        displayPopupContent(popup.getSelectedFeature());
                        dom.byId("featureCount").innerHTML = popup.features.length + " feature(s) selected";

                        //enable navigation if more than one feature is selected
                        popup.features.length > 1 ? domUtils.show(dom.byId("pager")) : domUtils.hide(dom.byId("pager"));
                    });
                }

                function displayPopupContent(feature) {
                    if (feature) {
                        var updateQuery = new RelationshipQuery();
                        updateQuery.objectIds = [feature.attributes[this.selectedLayer.objectIdField]];
                        updateQuery.returnGeometry = true;
                        updateQuery.outFields = ["*"];
                        updateQuery.relationshipId = this.selectedLayer.relationships[0].id;
                        this.selectedLayer.queryRelatedFeatures(updateQuery, lang.hitch(this, function (results) {
                            //If related record found, then set infotemplate of related table
                            if (results[feature.attributes[this.selectedLayer.objectIdField]]) {
                                results[feature.attributes[this.selectedLayer.objectIdField]].features[0].setInfoTemplate(new PopupTemplate(this.data.popupInfo));
                                //UnComment the  following two lines to see proper result
                                //var newLayer = new FeatureLayer(this.data.url);
                                //results[feature.attributes[this.selectedLayer.objectIdField]].features[0]._layer = newLayer;
                                setTimeout(function () {
                                    //get content of features and set it to left panel after specified time
                                    var content = results[feature.attributes[this.selectedLayer.objectIdField]].features[0].getContent();
                                    registry.byId("leftPane").set("content", content);
                                }, 500);
                            } else {
                                registry.byId("leftPane").set("content", "No Features Found");
                            }
                        }));
                    }
                }
            });
        });
    </script>
</head>

<body class="claro">
    <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer"
         data-dojo-props="design:'headline',gutters:false"
         style="width:100%; height:100%;">
        <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:false"
             region="left" style="width: 40%;height:100%;">
            <div id="leftPane" data-dojo-type="dijit/layout/ContentPane"
                 data-dojo-props="region:'center'"></div>
            <div id="header" data-dojo-type="dijit/layout/ContentPane"
                 data-dojo-props="region:'top'">
                <div id="featureCount" style="margin-bottom:5px;">Click to select feature(s)</div>
            </div>
        </div>
        <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
    </div>
</body>

</html>

View solution in original post

4 Replies
MeganGosch
New Contributor II

Hi Brad,

I'm trying to work on a similar problem ... I have polygons and points which has relationship classes defined between them.  I want a user to click on a polygon, and have the related point feature highlighted on the map.  This is for an asset management application.  The polygons don't necessarily contain the point within them, so can't build a select by location query.  I feel your pain as I don't have the js skills needed to make this work.  Sounds like you're close though. I hope someone has some good input for us!

RobertScheitlin__GISP
MVP Emeritus

Brad,

  This is not WAB widget code but the below is a JS sample that allows for related records query that you may be able to use as a starting point:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Test for domain fields in related table</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.15/dijit/themes/claro/claro.css" />
    <link rel="stylesheet" href="https://js.arcgis.com/3.15/esri/css/esri.css" />
    <style>
        html, body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
            margin: 0;
            font-family: "Open Sans";
        }
        #leftPane {
            width: 20%;
            margin: 0;
            border: none;
        }
        #map {
            padding: 0;
        }
    </style>
    <script src="https://js.arcgis.com/3.15/"></script>
    <script>
        require([
            "dojo/ready",
            "dojo/on",
            "dojo/_base/lang",
            'esri/tasks/RelationshipQuery',
            "dojo/dom",
            "dijit/registry",
            "dojo/dom-construct",
            "dojo/parser",
            "esri/map",
            "esri/arcgis/utils",
            "esri/domUtils",
            "esri/dijit/Popup",
            "esri/dijit/PopupTemplate",
            "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane"
        ], function (
            ready, on, lang, RelationshipQuery, dom, registry, domConstruct, parser, Map,
            arcgisUtils, domUtils, Popup, PopupTemplate, BorderContainer, ContentPane
        ) {
            ready(function () {

                parser.parse();
                //Create a map based on an ArcGIS Online web map id
                arcgisUtils.createMap("ba61bf1495494336ba347b3286389cd8", "map").then(function (response) {
                    window.map = response.map;
                    this.selectedLayer = map.getLayer(response.itemInfo.itemData.operationalLayers[0].id);
                    this.data = response.itemInfo.itemData.tables[0];
                    //set the popup's popupWindow property to false. This prevents the popup from displaying
                    map.infoWindow.set("popupWinow", false);
                    initializeSidebar(window.map);
                }, function (error) {
                    console.log("Map creation failed: ", dojo.toJson(error));
                });

                function initializeSidebar(map) {
                    var popup = map.infoWindow;

                    //when the selection changes update the side panel to display the popup info for the
                    //currently selected feature.
                    on(popup, "selection-change", function () {
                        displayPopupContent(popup.getSelectedFeature());
                    });

                    //when the selection is cleared remove the popup content from the side panel.
                    on(popup, "clear-features", function () {
                        dom.byId("featureCount").innerHTML = "Click to select feature(s)";
                        registry.byId("leftPane").set("content", "");
                        domUtils.hide(dom.byId("pager"));
                    });

                    //When features are associated with the  map's info window update the sidebar with the new content.
                    on(popup, "set-features", function () {
                        displayPopupContent(popup.getSelectedFeature());
                        dom.byId("featureCount").innerHTML = popup.features.length + " feature(s) selected";

                        //enable navigation if more than one feature is selected
                        popup.features.length > 1 ? domUtils.show(dom.byId("pager")) : domUtils.hide(dom.byId("pager"));
                    });
                }

                function displayPopupContent(feature) {
                    if (feature) {
                        var updateQuery = new RelationshipQuery();
                        updateQuery.objectIds = [feature.attributes[this.selectedLayer.objectIdField]];
                        updateQuery.returnGeometry = true;
                        updateQuery.outFields = ["*"];
                        updateQuery.relationshipId = this.selectedLayer.relationships[0].id;
                        this.selectedLayer.queryRelatedFeatures(updateQuery, lang.hitch(this, function (results) {
                            //If related record found, then set infotemplate of related table
                            if (results[feature.attributes[this.selectedLayer.objectIdField]]) {
                                results[feature.attributes[this.selectedLayer.objectIdField]].features[0].setInfoTemplate(new PopupTemplate(this.data.popupInfo));
                                //UnComment the  following two lines to see proper result
                                //var newLayer = new FeatureLayer(this.data.url);
                                //results[feature.attributes[this.selectedLayer.objectIdField]].features[0]._layer = newLayer;
                                setTimeout(function () {
                                    //get content of features and set it to left panel after specified time
                                    var content = results[feature.attributes[this.selectedLayer.objectIdField]].features[0].getContent();
                                    registry.byId("leftPane").set("content", content);
                                }, 500);
                            } else {
                                registry.byId("leftPane").set("content", "No Features Found");
                            }
                        }));
                    }
                }
            });
        });
    </script>
</head>

<body class="claro">
    <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer"
         data-dojo-props="design:'headline',gutters:false"
         style="width:100%; height:100%;">
        <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:false"
             region="left" style="width: 40%;height:100%;">
            <div id="leftPane" data-dojo-type="dijit/layout/ContentPane"
                 data-dojo-props="region:'center'"></div>
            <div id="header" data-dojo-type="dijit/layout/ContentPane"
                 data-dojo-props="region:'top'">
                <div id="featureCount" style="margin-bottom:5px;">Click to select feature(s)</div>
            </div>
        </div>
        <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
    </div>
</body>

</html>
MeganGosch
New Contributor II

Hi - just an fyi.  I was on the phone with Esri for quite a bit this morning working with their developer support staff.  Long story short, even though the documentation for AppBuilder says that it can support related tables within their Query widget, it can not. It's a known bug and has 2 enhancements logged in.  I'll try using this code as a starting point as well.

BUG-000087466 : Attribute Widget does not display the correct table name in Web App Builder for ArcGIS when clicking on 'Show Related Records'

ENH-000091041

Preeti Gupta (08:57:48):

Allow Web Map's pop-up configuration for the related table to be carried over to the Web AppBuilder app.

ENH-000082871

Provide the ability to Query Related Records in ArcGIS Online hosted application templates and Web AppBuilder, as it is available through pop-up configuration in the Map Viewer

BradJones
New Contributor III

Thank you.  I will use this as a starting point. 

0 Kudos