Error de widget FeatureTable

492
3
Jump to solution
04-23-2021 01:18 PM
vmvargas
New Contributor

Hello everyone,

I have problems with the FeatureTable widget with featureLayer, does not zoom to select feature and full extents the error that indicates is TypeError: Cannot read property 'targetGeometry' of null

Javascript ver. 4.19

Thank you

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.19/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.19/"></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 {
            height: 50%;
            width: 100%;
        }
    </style>

    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/core/watchUtils",
            "esri/layers/FeatureLayer",
            "esri/widgets/FeatureTable"
        ], function(MapMapViewwatchUtilsFeatureLayerFeatureTable) {

            const features = [];

            const featureLayer = new FeatureLayer({
                layerId: 15,
                title: "incidentes viales 2019"
            });

            const map = new Map({
                basemap: "streets-night-vector",
                layers: [featureLayer]
            });

            let view = new MapView({
                container: "viewDiv",
                map: map,
                zoom: 13,
                center: [-106.431.645],
                constraints: {
                    minScale: 400000
                },
                popup: {
                    autoOpenEnabled: false
                }
            });

            view.when(() => {
                const featureLayer = map.layers.getItemAt(0);
                featureLayer.title = "Ganador Elecciones 2019";

                const featureTable = new FeatureTable({
                    view: view,
                    layer: featureLayer,
                    fieldConfigs: [{
                        name: "PUNTOS_ID",
                        label: "Identificador",
                        direction: "asc"
                    }, {
                        name: "NOMBRE1",
                        label: "Calle 1"
                    }, {
                        name: "NOMBRE2",
                        label: "Calle 2"
                    }, {
                        name: "DISTRITO",
                        label: "Distrito SSPM"
                    }, {
                        name: "EXPEDIENTE",
                        label: "No. de Expediente"
                    }, {
                        name: "ACCI2019",
                        label: "Total de Eventos"
                    }, {
                        name: "SECTOR",
                        label: "No. de Sector"
                    }],
                    container: document.getElementById("tableDiv")
                });

                view.ui.add(document.getElementById("actions"), "top-right")


                featureLayer.watch("loaded", () => {
                    watchUtils.whenFalse(view"updating", () => {
                        if (view.extent) {
                            featureTable.filterGeometry = view.extent;
                        }
                    });
                });

                featureTable.on("selection-change", (changes=> {
                    changes.removed.forEach((item=> {
                        const data = features.find((data=> {
                            return data.feature === item.feature;
                        });
                        if (data) {
                            features.splice(features.indexOf(data), 1);
                        }
                    });

                    changes.added.forEach((item=> {
                        const feature = item.feature;
                        features.push({
                            feature: feature
                        });
                    });
                });

                view.on("immediate-click", (event=> {
                    view.hitTest(event).then((response=> {
                        const candidate = response.results.find((result=> {
                            return result.graphic && result.graphic.layer && result.graphic.layer === featureLayer;
                        });
                        candidate && featureTable.selectRows(candidate.graphic);
                    });
                });

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

                zoomBtn.addEventListener("click"zoomToSelectedFeature);
                fullExtentBtn.addEventListener("click"fullExtent);

                function zoomToSelectedFeature() {

                    const query = featureLayer.createQuery();

                    const featureIds = features.map((result=> {
                        return result.feature.getAttribute(featureLayer.objectIdField);
                    });

                    query.objectIds = featureIds;

                    query.returnGeometry = true;

                    featureLayer.queryFeatures(query).then((results=> {
                        view.goTo(results.features)
                            .catch((error=> {
                                if (error.name != "AbortError") {
                                    console.error(error);
                                }
                            });
                    });
                }

                function fullExtent() {

                    view.goTo(featureLayer.fullExtent)
                        .catch((error=> {
                            if (error.name != "AbortError") {
                                console.error(error);
                            }
                        });
                }
            });
        });
    </script>
</head>

<body>
    <div id="viewDiv"></div>
    <div class="container">
        <div id="tableDiv"></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>
    </div>
</body>

</html>

 

 

 

0 Kudos
1 Solution

Accepted Solutions
UndralBatsukh
Esri Regular Contributor

Hi there, 

What Jose said is correct. The reason you are not able to zoom into selected features and full extent is because the feature layer has a different spatial reference than the view's spatial reference. To solve this issue a few things need to be done in your app. 

In order to zoom to the selected features, please set the query.outSpatialReference to match the spatialReference of the view so that the returned results can be located on the map. See below:

 

 query.objectIds = featureIds;
 query.returnGeometry = true;
 query.outSpatialReference = view.spatialReference;

 

 

As for the fullExtent of the FeatureLayer, I'd suggest that you pass in a predefined extent that matches the view's spatialReference. If that is not an option then you can use the projection module's project method to project the fullExtent of your layer to match the spatialReference of the view.  But loading projection module for this case only maybe an overkill. 

 

 projection.load().then(function () {
  projectedFullExtent = projection.project(
   featureLayer.fullExtent,
   view.spatialReference
  );
});

 

 

Forgot to mention this initially... You have to reproject the fullExtent of your layer to match the spatial reference of the view because View.goTo does not project the geometries on the fly. We have an enhancement request for this. But for now, you have to project your geometry to match the spatial reference of the view before calling goTo. 

Here is an updated simple test app that shows how to zoom to fullExtent and selected features. 

Hope this helps,

-Undral

View solution in original post

0 Kudos
3 Replies
by Anonymous User
Not applicable

Hello,

I noticed the Spatial Reference of the layer has a wkid of 32613. The basemap you are using is "streets-night-vector" which has a wkid of 102100 (Web Mercator). If you comment out the basemap line of code in the Map constructor and refresh the app, you will notice the layer loads without a basemap, and if you select a record in the FeatureTable, you will now be able to highlight the feature and zoom to the selected feature. Can you verify this? This appears to be an issue caused by the spatial reference of the layer being distinct from the basemap's. 

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

What Jose said is correct. The reason you are not able to zoom into selected features and full extent is because the feature layer has a different spatial reference than the view's spatial reference. To solve this issue a few things need to be done in your app. 

In order to zoom to the selected features, please set the query.outSpatialReference to match the spatialReference of the view so that the returned results can be located on the map. See below:

 

 query.objectIds = featureIds;
 query.returnGeometry = true;
 query.outSpatialReference = view.spatialReference;

 

 

As for the fullExtent of the FeatureLayer, I'd suggest that you pass in a predefined extent that matches the view's spatialReference. If that is not an option then you can use the projection module's project method to project the fullExtent of your layer to match the spatialReference of the view.  But loading projection module for this case only maybe an overkill. 

 

 projection.load().then(function () {
  projectedFullExtent = projection.project(
   featureLayer.fullExtent,
   view.spatialReference
  );
});

 

 

Forgot to mention this initially... You have to reproject the fullExtent of your layer to match the spatial reference of the view because View.goTo does not project the geometries on the fly. We have an enhancement request for this. But for now, you have to project your geometry to match the spatial reference of the view before calling goTo. 

Here is an updated simple test app that shows how to zoom to fullExtent and selected features. 

Hope this helps,

-Undral

0 Kudos
vmvargas
New Contributor

Thank you UndralBatsukh, JoseBanuelos1and UndralBatsukh for taking the time to resolve my error

0 Kudos