Select to view content in your preferred language

Problem calling function from a list of selected features

5202
21
02-17-2015 02:39 PM
RyanSellman
Deactivated User

Hello,

In my app, I have a query set up that selects parcels from a feature layer.  After the query is executed, I loop through the selected features that are returned and populate a list showing basic attribute information of the selected features (2 fields for now).  In the created list, I am trying to make a button for each feature that would fire a function (searchParcelDetail) that takes the selected feature's OBJECTID and passes it into another query.  From here I can zoom to the parcel and show more attributes.  I am creating the button in line 51, for each selected parcel in the first query:

var parcel3Url = "http://summitmaps.summitoh.net/arcgis/rest/services/Fiscal_Mercator/MapServer/6";
  featureLayerParcelFor = new esri.layers.FeatureLayer(parcel3Url, {
  mode: esri.layers.FeatureLayer.MODE_SELECTION,
  visible: true,
  id: "Selected Parcels",
  outFields: ["PARID", "ALT_ID", "ADDR", "OWN1"]
  });
  var symbol2 = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new dojo.Color([100, 100, 100]), 2), new dojo.Color([0, 0, 255, 0.20]));
  featureLayerParcelFor.setSelectionSymbol(symbol2);
  map.addLayer(featureLayerParcelFor);

  
  featureLayerParcelDetail = new esri.layers.FeatureLayer(parcel3Url, {
  mode: esri.layers.FeatureLayer.MODE_SELECTION,
  visible: true,
  id: "Selected Parcels - Detailed",
  outFields: ["PARID", "ALT_ID", "ADDR", "OWN1", "OWNADDR1", "OWNZIP1", "CITYNAME", "STATECODE", "OWN2", "OWNADDR2", "OWNZIP2", "NBHD", "CLASS", "LUC", "ACRES", "DESC_"]
  });
  var symbol2 = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new dojo.Color([100, 100, 100]), 2), new dojo.Color([0, 0, 255, 0.20]));
  featureLayerParcelDetail.setSelectionSymbol(symbol2);
  map.addLayer(featureLayerParcelDetail);
   
   
  function queryParcels2() {
   
  var queryParcels = new esri.tasks.Query();
  queryParcels.where = "PARID LIKE '" + "%" + dom.byId("parcelText2").value + "'";


  featureLayerParcelFor.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {
   
  map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelFor.getSelectedFeatures()), true);

  });
  }
   
   

  featureLayerParcelFor.on("selection-complete", function(fset) {
  console.log("Selection Complete");
  var resultFeatures = fset.features;
  var details, number;


  details = "Number of parcels found: " + resultFeatures.length + "<br /><hr><table>";
  for (var i = 0, il = resultFeatures.length; i < il; i++) {
  number = i + 1;

  details = details + "<tr><td><b>    PARID:</b> " + resultFeatures.attributes.PARID + "</td></tr>";
  details = details + "<tr><td><b>    ALT_ID:</b> " + resultFeatures.attributes.ALT_ID + "</td></tr>";
  details = details + "<tr><td><button onClick=searchParcelDetail('" + resultFeatures.attributes.OBJECTID + "')>More Details</button></td></tr>";
  details = details + "<tr><td></td></tr>";
  details = details + "<tr><td><hr /></td></tr>";



  }
  details = details + "</table>";

  document.getElementById("parcelSearchResults").innerHTML = details;


  });
function searchParcelDetail(objectid){

  var queryParcels = new esri.tasks.Query();
  queryParcels.where = "OBJECTID = '" + objectid + "'";


  featureLayerParcelDetail.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {
   
  map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelDetail.getSelectedFeatures()), true);

  });
   
  dijit.byId("leftPane2").selectChild(dijit.byId("propertyDetails3"));

  }

Everything works until I try to click the button to fire the searchParcelDetail function. I get the error:

"Uncaught ReferenceError: searchParcelDetail is not defined"

Can anyone see what I am doing wrong?  To be honest I'm not sure if this is  the best way to accomplish this.  Any ideas?

Any help is appreciated!

Thanks,

Ryan

0 Kudos
21 Replies
RyanSellman
Deactivated User

Tom,

I appreciate the help but this issue is still getting the best of me today.  I tried to implement you recent suggestion but its still not working.  Is this what you were thinking?

featureLayerParcelFor.on("selection-complete", function(fset) {
             console.log("Selection Complete");
             var resultFeatures = fset.features;
             var details, number;




             details = "Number of parcels found: " + resultFeatures.length + "<br /><b>CLICK MORE DETAILS FOR DETAILED INFORMATION</b><hr><table>";
             for (var i = 0, il = resultFeatures.length; i < il; i++) {
   
  var parcelButton = new Button({
  label: "More Details",
  onClick: searchParcelDetail(resultFeatures.attributes.OBJECTID)
  }, "button"+i).startup();
   
                 number = i + 1;


                 details = details + "<tr><td>" + number + ". <b>Parcel #: </b>" + resultFeatures.attributes.PARID + "</td></tr><tr></tr>";


                 details = details + "<tr><td><b>    Alt_ID:</b> " + resultFeatures.attributes.ALT_ID + "</td></tr>";
                 details = details + "<tr><td><b>    Address:</b> " + resultFeatures.attributes.ADDR + "</td></tr>";
                 details = details + "<tr><td><b>    Owner:</b> " + resultFeatures.attributes.OWN1 + "</td></tr>";
  details = details + "<tr><td>    " + parcelButton + "</td></tr>";
                 details = details + "<tr><td></td></tr>";
                 details = details + "<tr><td><hr /></td></tr>";
   
             }
   
             details = details + "</table>";


             document.getElementById("parcelSearchResults").innerHTML = details;

         });


         function searchParcelDetail(objectid) {


             var queryParcels = new esri.tasks.Query();
   
             queryParcels.where = "OBJECTID = '" + objectid + "'";


             featureLayerParcelDetail.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {


                 map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelDetail.getSelectedFeatures()), true);


             });


         }

With the above in place, the button doesn't get created, instead it just says, "undefined" where the button should be.  Also, after hitting the  Search button that runs the first query, it automatically passes the OBJECTID into the searchParcelDetail function and executes the second query.  Not sure whats going on here.  The link I sent over earlier has been updated with these changes.

Sorry to pester!  Thank you for the help!

Ryan

0 Kudos
TomSellsted
MVP Regular Contributor

Ryan,

No worries!  You will get it.  Something like this.  You build the empty button and add it to the DOM and then attach the onClick event with a second loop.

             details = "Number of parcels found: " + resultFeatures.length + "<br /><b>CLICK PARCEL # FOR DETAILED INFORMATION</b><hr><table>";
             for (var i = 0, il = resultFeatures.length; i < il; i++) {
                 number = i + 1;


                 details = details + "<tr><td>" + number + ". <b>Parcel #: </b><a href=javascript:searchParcelDetail('" + resultFeatures.attributes.OBJECTID + "')>" + resultFeatures.attributes.PARID + "</a></td></tr><tr></tr>";


                 details = details + "<tr><td><b>    Alt_ID:</b> " + resultFeatures.attributes.ALT_ID + "</td></tr>";
                 details = details + "<tr><td><b>    Address:</b> " + resultFeatures.attributes.ADDR + "</td></tr>";
                 details = details + "<tr><td><b>    Owner:</b> " + resultFeatures.attributes.OWN1 + "</td></tr>";
                 details = details + "<tr><td><button id='button" + i + "'>More Details</button></td></tr>";
                 details = details + "<tr><td></td></tr>";
                 details = details + "<tr><tr><hr /></td></tr>";
                 on(dom.byId("button" + i), "click", searchParcelDetail(resultFeatures.attributes.OBJECTID));
             }




             details = details + "</table>";

             document.getElementById("parcelSearchResults").innerHTML = details;


             for (var i = 0, il = resultFeatures.length; i < il; i++) {
  var parcelButton = new Button({  
  label: "More Details",  
  onClick: searchParcelDetail(resultFeatures.attributes.OBJECTID)  
  }, "button"+i).startup();
  }
  }
RyanSellman
Deactivated User

Thanks for all the help, but still no luck.  I understand the logic but can't get it to work correctly.  After inserting your code I am still having similar issues.  Both queries are firing and I get this error:

TypeError: Cannot read property 'on' of null

I will keep plugging away at it!!  If you can think of anything else I am missing, let me know!

Here is what is in place now:

featureLayerParcelFor.on("selection-complete", function(fset) {
             console.log("Selection Complete");
             var resultFeatures = fset.features;
             var details, number;




             details = "Number of parcels found: " + resultFeatures.length + "<br /><b>CLICK PARCEL # FOR DETAILED INFORMATION</b><hr><table>";
             for (var i = 0, il = resultFeatures.length; i < il; i++) {
                 number = i + 1;




                 details = details + "<tr><td>" + number + ". <b>Parcel #: </b>" + resultFeatures.attributes.PARID + "</td></tr><tr></tr>";


                 details = details + "<tr><td><b>    Alt_ID:</b> " + resultFeatures.attributes.ALT_ID + "</td></tr>";
                 details = details + "<tr><td><b>    Address:</b> " + resultFeatures.attributes.ADDR + "</td></tr>";
                 details = details + "<tr><td><b>    Owner:</b> " + resultFeatures.attributes.OWN1 + "</td></tr>";
                 details = details + "<tr><td><button id='button" + i + "'>More Details</button></td></tr>";
                 details = details + "<tr><td></td></tr>";
                 details = details + "<tr><tr><hr /></td></tr>";
                 on(dom.byId("button" + i), "click", searchParcelDetail(resultFeatures.attributes.OBJECTID));
             }


             details = details + "</table>";


             document.getElementById("parcelSearchResults").innerHTML = details;




             for (var i = 0, il = resultFeatures.length; i < il; i++) {
                 var parcelButton = new Button({
                     label: "More Details",
                     onClick: searchParcelDetail(resultFeatures.attributes.OBJECTID)
                 }, "button" + i).startup();
             }
             

        });


         function searchParcelDetail(objectid) {


             var queryParcels = new esri.tasks.Query();
   
             queryParcels.where = "OBJECTID = '" + objectid + "'";


             featureLayerParcelDetail.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {


                 map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelDetail.getSelectedFeatures()), true);


             });


         }

Thanks again for all the help!

0 Kudos
TomSellsted
MVP Regular Contributor

Ryan,

It looks like you still have the on statement in your logic (line 25 from your last post).  That should definitely be removed.

Also the featureLayerParcel.on is free floating in your code.  It is not contained in any other function or logic.  Is this on purpose?

Regards,

Tom

0 Kudos
RyanSellman
Deactivated User

Ok, so I removed line 25 from the code.  Not sure why I left that there - my mistake.

When I hit the search button now, both query's are still firing and when I hit the created "More Details" button the console says "Uncaught TypeError: undefined is not a function". 

The featureLayerParcel.on is not free floating for a certain reason.  Should the method be removed, or perhaps stuck in the queryParcels2() function?

Thanks,

Ryan

0 Kudos
TomSellsted
MVP Regular Contributor

Ryan,

You are using that function to form a list to be displayed, so it should be used when you are ready to create that list to be displayed.  Not knowing your application that well, but it would see like you would want to run it only when you were viewing the Select Parcel and Filter by Class dialog was opened.

Otherwise it is running as soon as the javascript is loaded.  That may be what you want though.

Regards,

Tom

0 Kudos
RyanSellman
Deactivated User

Tom,

I definitely want the function to run when I am ready for the list to be displayed (i.e. when I do the parcel search in the "Property Search" pane).  I made a few modifications so now that code is executed in the callback function of the feature layer selection, but its still not right:

function queryParcels2() {
   
  var queryParcels = new esri.tasks.Query();
  queryParcels.where = "PARID LIKE '" + "%" + dom.byId("parcelText2").value + "'";


  featureLayerParcelFor.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {
   
  map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelFor.getSelectedFeatures()), true);
   
   
  console.log("Selection Complete");  
  var resultFeatures = features;
  console.log(resultFeatures);  
  var details, number; 
   
  details = "Number of parcels found: " + resultFeatures.length + "<br /><b>CLICK PARCEL # FOR DETAILED INFORMATION</b><hr><table>";  
   
  for (var i = 0, il = resultFeatures.length; i < il; i++) {  
  number = i + 1;  
   
  details = details + "<tr><td>" + number + ". <b>Parcel #: </b>" + resultFeatures.attributes.PARID + "</td></tr><tr></tr>";  
   
  details = details + "<tr><td><b>    Alt_ID:</b> " + resultFeatures.attributes.ALT_ID + "</td></tr>";  
  details = details + "<tr><td><b>    Address:</b> " + resultFeatures.attributes.ADDR + "</td></tr>";  
  details = details + "<tr><td><b>    Owner:</b> " + resultFeatures.attributes.OWN1 + "</td></tr>";  
  details = details + "<tr><td><button id='button" + i + "'>More Details</button></td></tr>";  
  details = details + "<tr><td></td></tr>";  
  details = details + "<tr><tr><hr /></td></tr>";    
  }  
   
  details = details + "</table>";  
   
  document.getElementById("parcelSearchResults").innerHTML = details; 
   
  for (var i = 0, il = resultFeatures.length; i < il; i++) {  
  var parcelButton = new Button({  
  label: "More Details",  
  onClick: searchParcelDetail(resultFeatures.attributes.OBJECTID)  
  }, "button" + i).startup();  
  }

  });
   
  }

  
         function searchParcelDetail(objectid) {  
  
  
             var queryParcels = new esri.tasks.Query();  
     
             queryParcels.where = "OBJECTID = '" + objectid + "'";  
  
  
             featureLayerParcelDetail.selectFeatures(queryParcels, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {  
  
  
  map.setExtent(graphicsUtils.graphicsExtent(featureLayerParcelDetail.getSelectedFeatures()), true);  

  
             });  
  
  
         }

I still do not understand why the searchParcelDetail function is being executed when I click the search button that's registered to execute the queryParcels2 function...

Ryan

0 Kudos
TomSellsted
MVP Regular Contributor

Ryan,

I looked at your development version and it still shows the second featureLayerParcelFor.on statement.  Is this the latest version of your app?

Regards,

Tom

0 Kudos
RyanSellman
Deactivated User

I am sorry no, I should have mentioned that.  I am at home now working off my PC with a different version of the app which is inaccessible to the internet.  My apologies!  When I get in tomorrow I will definitely update the development project so that it reflects the code from my previous reply.

I set some breakpoints in the app I am running on my PC here and the second query (which takes an objectid as its argument) is being fired during the second loop, which is where we create each button and attach the onClick event to them.

Ryan

0 Kudos
TomSellsted
MVP Regular Contributor

Ryan,

I understand.  No problem.  I was using Chrome's developer tools to try and look closer at your code. 

My apologies, I will be out of the office, out of town for the remainder of the week.

Regards,

Tom

0 Kudos