I want to click on a point to display attributes from a feature server. The only tutorial/sample I could find was from App Studio v1.4 sample on github and too much has changed to get it working.
Currently my code looks like this
onMouseClicked: {
var tolerance = 22;
var returnPopupsOnly = false;
var maximumResults = 1;
mapView.identifyLayerWithMaxResults(featureLayer, mouse.x, mouse.y, tolerance, returnPopupsOnly, maximumResults);
}
onIdentifyLayerStatusChanged: {
if (identifyLayerStatus === Enums.TaskStatusCompleted) {
featureLayer.clearSelection();
var identifiedObjects = [];
for (var i = 0; i < identifyLayerResult.geoElements.length; i++){
var elem = identifyLayerResult.geoElements[i];
identifiedObjects.push(elem);
}
var count = identifyLayerResult.geoElements.length;
featureLayer.selectFeatures(identifiedObjects);
}
} Which is just code I took from the selecting feature app sample. I have this codeonSelectFeaturesStatusChanged: {
if (selectFeaturesStatus === Enums.TaskStatusCompleted) {if (!selectFeaturesResult.iterator.hasNext)return;selectedFeature = selectFeaturesResult.iterator.next();value= selectedFeature.attributes.attributeValue("attributeValue");console.log(value)}
but it does not get invoked because selectFeatures apparently doesn't callonSelectFeaturesStatusChanged? I find this all very frustrating, this should be extremely simple to do but there is no documentation that has been properly maintained That even suggests how to properly accomplish this.
Solved! Go to Solution.
Hi Kyle,
Sorry to hear that. Yes it is quite simple to get attributes from the GeoElement. GeoElement has a sub class called Feature and Feature provides a property called attributes which is a ListModel (the model name is AttributeListModel in Runtime) that has the attribute names and value listed.
However, showing it in a dialog or a popup is a UI aspect and it can vary on the users requirement. This can be done in many ways.
AttributeListModel QML Type | ArcGIS for Developers
But just to give you a proof of concept I have provided a code snippet below for you to show how we can tweak the Feature Layer Selection Sample to show the feature attributes when you click on the feature. In this sample I have added a Dialog known as Pane which show all the attribute values along with the name using the AttributeListModel to show the attributes.
property real scaleFactor: AppFramework.displayScaleFactor
property string displayText: "Click or tap to select features."
ListModel{
id:displayAttributesModel
}
// Map view UI presentation at top
MapView {
id: mapView
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: messageBar.top
}
wrapAroundMode: Enums.WrapAroundModeDisabled
Map {
id: map
BasemapStreets {}
FeatureLayer {
id: featureLayer
selectionColor: "cyan"
selectionWidth: 3
// feature table
ServiceFeatureTable {
id: featureTable
url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0"
}
}
onLoadStatusChanged: {
if (loadStatus === Enums.LoadStatusLoaded) {
mapView.setViewpoint(viewPoint);
}
}
}
// initial viewpoint
ViewpointCenter {
id: viewPoint
Point {
x: -10800000
y: 4500000
spatialReference: SpatialReference {
wkid: 102100
}
}
targetScale: 3e7
}
//! [identify feature layer qml api snippet]
onMouseClicked: {
var tolerance = 22;
var returnPopupsOnly = false;
var maximumResults = 1000;
mapView.identifyLayerWithMaxResults(featureLayer, mouse.x, mouse.y, tolerance, returnPopupsOnly, maximumResults);
}
onIdentifyLayerStatusChanged: {
if (identifyLayerStatus === Enums.TaskStatusCompleted) {
// clear any previous selections
featureLayer.clearSelection();
displayAttributesModel.clear();
// create an array to store the features
var identifiedObjects = [];
for (var i = 0; i < identifyLayerResult.geoElements.length; i++){
var elem = identifyLayerResult.geoElements;
identifiedObjects.push(elem);
displayAttributesModel.append(elem);
}
// cache the number of identifyLayerResult
var count = identifyLayerResult.geoElements.length;
// select the features in the feature layer
featureLayer.selectFeatures(identifiedObjects);
displayText = "%1 %2 selected.".arg(count).arg(count > 1 ? "features" : "feature");
}
}
//! [identify feature layer qml api snippet]
// Busy Indicator
BusyIndicator {
anchors.centerIn: parent
height: 48 * scaleFactor
width: height
running: true
Material.accent:"#8f499c"
visible: (mapView.drawStatus === Enums.DrawStatusInProgress)
}
}
Pane {
id: attributeViewDialog
Material.primary: "white"
Material.elevation:2
padding: 5 * scaleFactor
visible: displayAttributesModel.count > 0
x: 10 * scaleFactor
y: 10 * scaleFactor
SwipeView{
id:swipeView
implicitHeight: 150 * scaleFactor
implicitWidth: 175 * scaleFactor
clip: true
Repeater {
model:displayAttributesModel
Rectangle{
color: "white"
clip: true
Flickable {
anchors.fill:parent
contentWidth:parent.width
contentHeight: popupColumn.height
clip: true
flickableDirection: Flickable.VerticalFlick
ColumnLayout {
id: popupColumn
width: parent.width * 0.95
anchors.horizontalCenter: parent.horizontalCenter
spacing: 3 * scaleFactor
clip: true
Text {
Layout.preferredWidth: parent.width
id:itemDesc
text: attributes.attributeValue("objectid")
elide: Text.ElideRight
color: "red"
font {
family: "serif"
pixelSize: 14 * scaleFactor
bold: true
}
renderType: Text.NativeRendering
}
Rectangle {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 2 * scaleFactor
color: "black"
}
Repeater {
model: attributes
RowLayout {
Layout.fillWidth: true
clip: true
spacing: 5 * scaleFactor
Text {
Layout.preferredWidth: popupColumn.width * 0.55
Layout.fillHeight: true
text: attributeName
wrapMode: Text.WrapAnywhere
font.pixelSize: 12 * scaleFactor
color: "gray"
}
Text {
Layout.fillWidth: true
Layout.fillHeight: true
text:attributeValue
wrapMode: Text.WrapAnywhere
font.pixelSize: 12 * scaleFactor
color: "#4f4f4f"
}
}
}
}
}
}
}
}
}
Rectangle {
id: messageBar
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: 30 * scaleFactor
color: "lightgrey"
border {
width: 0.5 * scaleFactor
color: "black"
}
Text {
id: msgText
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10 * scaleFactor
}
text: displayText
font.pixelSize: 14 * scaleFactor
}
}
If you notice in the code I added a SwipeView within the Pane to accommodate multiple selected features. Hence you can swipe horizontally to get to the next feature attributes if you would like.
I hope you find this useful. Thank you.
Nakul
Hi Kyle,
Sorry to hear that. Yes it is quite simple to get attributes from the GeoElement. GeoElement has a sub class called Feature and Feature provides a property called attributes which is a ListModel (the model name is AttributeListModel in Runtime) that has the attribute names and value listed.
However, showing it in a dialog or a popup is a UI aspect and it can vary on the users requirement. This can be done in many ways.
AttributeListModel QML Type | ArcGIS for Developers
But just to give you a proof of concept I have provided a code snippet below for you to show how we can tweak the Feature Layer Selection Sample to show the feature attributes when you click on the feature. In this sample I have added a Dialog known as Pane which show all the attribute values along with the name using the AttributeListModel to show the attributes.
property real scaleFactor: AppFramework.displayScaleFactor
property string displayText: "Click or tap to select features."
ListModel{
id:displayAttributesModel
}
// Map view UI presentation at top
MapView {
id: mapView
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: messageBar.top
}
wrapAroundMode: Enums.WrapAroundModeDisabled
Map {
id: map
BasemapStreets {}
FeatureLayer {
id: featureLayer
selectionColor: "cyan"
selectionWidth: 3
// feature table
ServiceFeatureTable {
id: featureTable
url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0"
}
}
onLoadStatusChanged: {
if (loadStatus === Enums.LoadStatusLoaded) {
mapView.setViewpoint(viewPoint);
}
}
}
// initial viewpoint
ViewpointCenter {
id: viewPoint
Point {
x: -10800000
y: 4500000
spatialReference: SpatialReference {
wkid: 102100
}
}
targetScale: 3e7
}
//! [identify feature layer qml api snippet]
onMouseClicked: {
var tolerance = 22;
var returnPopupsOnly = false;
var maximumResults = 1000;
mapView.identifyLayerWithMaxResults(featureLayer, mouse.x, mouse.y, tolerance, returnPopupsOnly, maximumResults);
}
onIdentifyLayerStatusChanged: {
if (identifyLayerStatus === Enums.TaskStatusCompleted) {
// clear any previous selections
featureLayer.clearSelection();
displayAttributesModel.clear();
// create an array to store the features
var identifiedObjects = [];
for (var i = 0; i < identifyLayerResult.geoElements.length; i++){
var elem = identifyLayerResult.geoElements;
identifiedObjects.push(elem);
displayAttributesModel.append(elem);
}
// cache the number of identifyLayerResult
var count = identifyLayerResult.geoElements.length;
// select the features in the feature layer
featureLayer.selectFeatures(identifiedObjects);
displayText = "%1 %2 selected.".arg(count).arg(count > 1 ? "features" : "feature");
}
}
//! [identify feature layer qml api snippet]
// Busy Indicator
BusyIndicator {
anchors.centerIn: parent
height: 48 * scaleFactor
width: height
running: true
Material.accent:"#8f499c"
visible: (mapView.drawStatus === Enums.DrawStatusInProgress)
}
}
Pane {
id: attributeViewDialog
Material.primary: "white"
Material.elevation:2
padding: 5 * scaleFactor
visible: displayAttributesModel.count > 0
x: 10 * scaleFactor
y: 10 * scaleFactor
SwipeView{
id:swipeView
implicitHeight: 150 * scaleFactor
implicitWidth: 175 * scaleFactor
clip: true
Repeater {
model:displayAttributesModel
Rectangle{
color: "white"
clip: true
Flickable {
anchors.fill:parent
contentWidth:parent.width
contentHeight: popupColumn.height
clip: true
flickableDirection: Flickable.VerticalFlick
ColumnLayout {
id: popupColumn
width: parent.width * 0.95
anchors.horizontalCenter: parent.horizontalCenter
spacing: 3 * scaleFactor
clip: true
Text {
Layout.preferredWidth: parent.width
id:itemDesc
text: attributes.attributeValue("objectid")
elide: Text.ElideRight
color: "red"
font {
family: "serif"
pixelSize: 14 * scaleFactor
bold: true
}
renderType: Text.NativeRendering
}
Rectangle {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 2 * scaleFactor
color: "black"
}
Repeater {
model: attributes
RowLayout {
Layout.fillWidth: true
clip: true
spacing: 5 * scaleFactor
Text {
Layout.preferredWidth: popupColumn.width * 0.55
Layout.fillHeight: true
text: attributeName
wrapMode: Text.WrapAnywhere
font.pixelSize: 12 * scaleFactor
color: "gray"
}
Text {
Layout.fillWidth: true
Layout.fillHeight: true
text:attributeValue
wrapMode: Text.WrapAnywhere
font.pixelSize: 12 * scaleFactor
color: "#4f4f4f"
}
}
}
}
}
}
}
}
}
Rectangle {
id: messageBar
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: 30 * scaleFactor
color: "lightgrey"
border {
width: 0.5 * scaleFactor
color: "black"
}
Text {
id: msgText
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10 * scaleFactor
}
text: displayText
font.pixelSize: 14 * scaleFactor
}
}
If you notice in the code I added a SwipeView within the Pane to accommodate multiple selected features. Hence you can swipe horizontally to get to the next feature attributes if you would like.
I hope you find this useful. Thank you.
Nakul
What libraries are you importing to get this to work?
If you are using Appstudio 3.0. Then the sample should have the libraries listed below
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Material 2.1
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Controls 1.0
import Esri.ArcGISRuntime 100.2
Thank you for your response
.
Is it possible to control which values are displayed? I don't want some of the fields being displayed visible