You are viewing limited content. For full access, please sign in.

Discussion

Discussion

HOWTO: Use a ESRI ArcGIS Online Map in Forms 10.x

posted on August 6, 2020 Show version history

Due to the ever growing restrictions of using Google Maps I decided to quickly pull together a way to use our own ArcGIS Online maps for use in our internal and external Laserfiche Forms.

By utilizing ESRI’s ArcGIS JavaScript 4.x library and your own in-house or Online ArcGIS Server you can easily add a map to your form. The map can even perform functions such as searching for locations and even reverse geocode map clicks which can then fill out a location text box or even a Laserfiche Form Address block.

This sample also allows you to use your own ArcGIS portal maps. Simply fill in the portal id and url variables in the code to access it.

Learn more about ESRI ArcGIS Online at https://www.arcgis.com/index.html and https://developers.arcgis.com/javascript/

To begin create a new Laserfiche Form and add a Custom HTML Element to it. Copy and paste the following html code in the HTML content of the element:

<div id="viewDiv"></div>

In the CSS and JavaScript section of the form designer copy and paste the following code:

CSS

@import "https://js.arcgis.com/4.16/esri/themes/light/main.css";

#viewDiv {
  padding: 0;
  margin: 0;
  height: 600px;
  width: 100%;
  background-color: #ffffff;
}

JavaScript

// Name ID of the field that will hold the returned latitude
var field_lat = "Field2";

// Name ID of the field that will hold the returned longitude
var field_lon = "Field3";

// Name ID of the field that will hold the returned location data
var field_location = "Field4";

// LF Forms Address Block Name ID
var field_address_block = 'Field5';

// Name ID of the DIV element that will display the map. This name should also match the one used in the CSS
var map_container = "viewDiv"

// Name of the basemap that will be used
// ESRI Basemaps - topo,streets,satellite,hybrid,dark-gray,gray,national-geographic,oceans,osm,terrain,dark-gray-vector,gray-vector,streets-vector,streets-night-vector,streets-navigation-vector,topo-vector,streets-relief-vector
var default_basemap = "topo-vector";

// Starting map center latitude
var start_lat = 33.52638;

// Starting map center longitude
var start_lon = -81.72373;

// Starting zoom level
var start_zoom = 12;

// Location of the map search box
var map_searchbox_location = "top-right";

// URL of the ArcGis JavaScript Library
var arcgis_script_url = "https://js.arcgis.com/4.16/";

// Cache the ArcGIS JavaScript Library?
var arcgis_script_cache = true;

// Rounding factor for clicked latitude and longitude
var latlon_factor = 100000000000000;

// Portal Map Options. ID and URL are required
var portal_map_id = "";

var portal_map_url = "";

// Click marker symbol variables
// Click marker style
var marker_symbol_click = "simple-marker";

// Click marker type
var marker_symbol_type = "point";

// Click marker symbol color [r,g,b]
var marker_symbol_color = [255,10,10];

// Click marker outline color [r,g,b]
var marker_symbol_outline_color = [255,255,255];

// Click marker outline width
var marker_symbol_outline_width = 2;

// Turn on/off console loging
var debug = true;

$.ajax({
    url: arcgis_script_url,
    cache: arcgis_script_cache,
    dataType: "script",
    success: function(data){
    require(["esri/portal/PortalItem",
             "esri/tasks/Locator",
             "esri/widgets/Search",
             "esri/views/MapView", 
             "esri/WebMap",
             "esri/Graphic"],
            function (PortalItem,
                       Locator,
                       Search,
                       MapView,
                       WebMap,
                       Graphic) {
     
 
      var webmap = new WebMap({});
      
      if(!portal_map_url.length == 0 && !portal_map_id.length == 0){
        
        webmap.portalItem = new PortalItem({portal: portal_map_url,
                                            id: portal_map_id
                                           });
      
      }else{
      
        webmap.basemap = default_basemap;
      
      }
      
      var view = new MapView({
        map: webmap,
        container: map_container,
        center: [start_lon,start_lat],
        zoom: start_zoom,
      });
      

      var search = new Search({
        view: view, 
        resultGraphicEnabled: false,
        popupEnabled: true
      });
      
      search.on("select-result", function(evt){
        
        if(debug)
          console.log("The selected search result: ", JSON.stringify(evt));        
      
      });
      
      view.ui.add(search, map_searchbox_location);      
      
        view.on("click", function(evt) {
          
          if(debug)
            console.log('Click event object: '+ JSON.stringify(evt));
          
          var lat = Math.round(evt.mapPoint.latitude * latlon_factor) / latlon_factor;
          var lon = Math.round(evt.mapPoint.longitude * latlon_factor) / latlon_factor;
          
          if(debug){
            console.log('Clicked Latitude: '+ evt.mapPoint.latitude + ' (Rounded: '+ lat +')');
            console.log('Clicked Longitude: '+ evt.mapPoint.longitude + ' (Rounded: '+ lon +')');
          }
          
          if(!field_lat.length == 0)
            $('#'+ field_lat).val(lat);
          
          if(!field_lon.length == 0)
            $('#'+ field_lon).val(lon);
          
          
          search.clear();
          
          view.popup.clear();
          
          reverse_geocode(search,evt);
          
          var graphic = new Graphic({
            geometry: {
              type: marker_symbol_type,
              latitude: evt.mapPoint.latitude,
              longitude: evt.mapPoint.longitude,
              spatialReference: view.spatialReference,
            },
            symbol: {
              type: marker_symbol_click,
              color: marker_symbol_color,
              outline: {
                color: marker_symbol_outline_color,
                width: marker_symbol_outline_width,
              },
            },
          });
          
          view.graphics.removeAll();
          view.graphics.add(graphic);   
          
        });  
      
      });  
    }
   });


function reverse_geocode(search,evt){
 
            if (search.activeSource) {
            var geocoder = search.activeSource.locator; //Defaults to ESRI World Geocode Service
            var params = {location: evt.mapPoint};
            geocoder.locationToAddress(params).then(
              function (response) {
                
                if(debug)
                  console.log('Geocoder response object: '+ JSON.stringify(response));
                
                if(debug)
                  console.log('Address object for '+ JSON.stringify(evt) +': ' + response.address);
                
                var location_attributes = response.attributes;
                
                // Location
                if(!field_location.length == 0)
                  $('#'+ field_location).val(location_attributes.LongLabel);
                
                // Address Block - Street Address
                var field_address_street = field_address_block +'_DSG0';
                if(!field_address_street.length == 0)
                  $('#'+ field_address_street).val(location_attributes.Address);
                
                // Address Block - Address Line 2
                var field_address_two = field_address_block +'_DSG1';
                if(!field_address_two.length == 0)
                  $('#'+ field_address_two).val(location_attributes.Block);
                
                // Address Block - City
                var field_address_city = field_address_block +'_DSG2';
                if(!field_address_city.length == 0)
                  $('#'+ field_address_city).val(location_attributes.City);
                
                // Address Block - State / Province / Region
                var field_address_state_province_region = field_address_block +'_DSG3';
                if(!field_address_state_province_region.length == 0)
                  $('#'+ field_address_state_province_region).val(location_attributes.Region + ' ' + location_attributes.Territory);
                
                // Address Block - Postal / Zip Code
                var field_address_postal_zip_code = field_address_block +'_DSG4';
                if(!field_address_postal_zip_code.length == 0)
                  $('#'+ field_address_postal_zip_code).val(location_attributes.Postal);
                
                // Address Block - Country
                var field_address_country = field_address_block +'_DSG5';
                if(!field_address_country.length == 0)
                  $('#'+ field_address_country).val(location_attributes.CountryCode);
                   
                
              },
              function (err) {
                
                if(debug)
                	console.log('No address object found at: ' + JSON.stringify(evt.mapPoint));
                
                if(!field_location.length == 0)
                  ('#'+ field_location).val ("No address found.");
              });
          }
  
}

After applying all the code save the form and click the preview button.

 

Hope this helps and corrections are always welcomed!

Wesley Funderberg

Screenshot_2020-08-06 Preview.png
7 0
replied on September 1, 2023

Hi Wes,

 

Please could you help me with using the same map to verify a geo location.

In my approval form, I need to show the geo location on the map based on  a geo location forms module but then, if the location is incorrect, I would like to be able to make the neccesary change by clicking in the correct location and then updating the address, location etc.

 

Would you be able to assist?

Thanks so much and well done on the solution.

0 0
replied on May 12, 2023 Show version history

Hey, I'm trying to get this going. Our GIS team has our own maps posted, which I have working with this code. I'm trying to get it to use our own geocoder service so it picks up the most up to date addressing we do ourselves. Referencing the geocoder URL alone as a string in that javascript doesn't seem to do it. Eventually, the goal is to have it look up current addressing and also to have it return some other map layer fields in the response, like whether or not they're in city limits. Can you point me in the right direction for some of this?

 

function reverse_geocode(search,evt){
 
            if (search.activeSource) {
            var geocoder = "https://MYURLHERE.URL/arcgis/rest/services/GeocodeCityworks/GeocodeServer" //search.activeSource.locator; //Defaults to ESRI World Geocode Service
            var params = {location: evt.mapPoint};
            geocoder.locationToAddress(params).then(
              function (response) {
                
                //if(debug)
                  console.log('Geocoder response object: '+ JSON.stringify(response));
                
                if(debug)
                  console.log('Address object for '+ JSON.stringify(evt) +': ' + response.address);
                
                var location_attributes = response.attributes;

Wondering if this is the right place to try to add/change the geocoder and if its a URL that's needed.

The console output still shows the ESRI worldwide geocoder service in the response.

 

Also, I tried moving to the newest version of js posted, 4.26, but 4.21 is as far as I can go before things break. I haven't ever done too much with GIS, so I'm just getting into some of this. Any help is appreciated.

0 0
replied on May 12, 2023

Hey Michael!

To make this work with your own geocoding service you will need to add/modify the following code:

1. Copy and paste the following code above the "var search = new Search({" section (line 106)

var my_geocoder = new Locator({url: "URL_TO_YOUR_GEOCODE_SERVER"});

2. Modify the "var search = new Search" section to match the following

var search = new Search({
    view: view,
    resultGraphicEnabled: false,
    popupEnabled: true,
    sources: [{
        locator: my_geocoder
     }]
});

3. Save the file and refresh the page.

The search service should default to your own geocoder instead of the ESRI World Geocode Service.

 

Hope this helps!

Wesley Funderberg

 

0 0
replied on January 23, 2023 Show version history

Can you elaborate on how you extract the location details from the map and put them into the Address field?  I was able to populate the Lat/Long and "Location" but I cant seem to get the Address fields to populate.

0 0
replied on January 23, 2023 Show version history

Dillan,

In my code, my address block field had the id of "Field5" but yours may be different. One way of discovering the ID name of yours is to click on the "CSS and JavaScript" tab in the form editor and look at the number that has been assigned to the address block (see screenshot). For example, mine said "q2" which meant it would give it the ID of "Field2".

Once you have the correct field ID, make sure you update the following bit of code:

// LF Forms Address Block Name ID
var field_address_block = 'Field2';

Hope this helps!

Wesley Funderberg

Screenshot 2023-01-23 at 16-00-54 CSS and JavaScript Laserfiche Forms.png
1 0
replied on January 23, 2023

This worked!  Thanks I hoped it was something simple.

0 0
replied on January 23, 2023

That's great to hear Dillan!

0 0
replied on September 8, 2022

Hi Wes!  

I used your code and our City Management loves it! 

I am trying to figure out how to display the pointer after a user saves the form as a draft.  

Any ideas?

Thanks!

Pete

0 0
replied on September 9, 2022

Hello Pete,

 So glad to hear it! Hopefully I can tackle that issue soon as I am needing to do the same. If I come up with something, I will post the update here.

 

Thanks!

0 0
replied on March 1, 2021

This is a great start for what I'm trying to do.  Is there a way to use LF Forms' Geolocation element, defaulted to Current Location, to feed a Latitude and Longitude to your code and return a City and State?

 

0 0
replied on March 5, 2021

Mike,

Please know that I quickly threw this together with only minimal testing done. Make sure that you place the current_location value as the Default value in a GeoLocation form module or it will not work.

 

@import "https://js.arcgis.com/4.18/esri/themes/light/main.css";

#viewDiv {
  padding: 0;
  margin: 0;
  height: 600px;
  width: 100%;
  background-color: #ffffff;
}
var mapview;
var clickpoint;
var search;

// Name ID of the field that will hold the returned latitude
var field_lat = "Field2";

// Name ID of the field that will hold the returned longitude
var field_lon = "Field3";

// Name ID of the field that will hold the returned location data
var field_location = "Field4";

// LF Forms Address Block Name ID
var field_address_block = 'Field5';

// Name ID of the DIV element that will display the map. This name should also match the one used in the CSS
var map_container = "viewDiv"

// Name of the basemap that will be used
// ESRI Basemaps - topo,streets,satellite,hybrid,dark-gray,gray,national-geographic,oceans,osm,terrain,dark-gray-vector,gray-vector,streets-vector,streets-night-vector,streets-navigation-vector,topo-vector,streets-relief-vector
var default_basemap = "topo-vector";

// Starting map center latitude
var start_lat = 33.52638;

// Starting map center longitude
var start_lon = -81.72373;

// Starting zoom level
var start_zoom = 12;

// Location of the map search box
var map_searchbox_location = "top-right";

// URL of the ArcGis JavaScript Library
var arcgis_script_url = "https://js.arcgis.com/4.18/";

// Cache the ArcGIS JavaScript Library?
var arcgis_script_cache = true;

// Rounding factor for clicked latitude and longitude
var latlon_factor = 100000000000000;

// Portal Map Options. ID and URL are required
var portal_map_id = ""//"72cbb6c5169540dbb29e30babb2c56b9";

var portal_map_url = ""//"https://aiken-sc.maps.arcgis.com";

// Click marker symbol variables
// Click marker style
var marker_symbol_click = "simple-marker";

// Click marker type
var marker_symbol_type = "point";

// Click marker symbol color [r,g,b]
var marker_symbol_color = [255,10,10];

// Click marker outline color [r,g,b]
var marker_symbol_outline_color = [255,255,255];

// Click marker outline width
var marker_symbol_outline_width = 2;

// Turn on/off console loging
var debug = true;

$(function() {
  
  var observer = new MutationObserver(function(e) {
    
    var lat = $(".geo-current-value[latitude][longitude]:eq(0)").attr('latitude');
    var lon = $(".geo-current-value[latitude][longitude]:eq(0)").attr('longitude');
    
    clickpoint.latitude = lat;
    clickpoint.longitude = lon;
    
    if(debug)
      console.log(JSON.stringify(clickpoint));
    
    reverse_geocode(clickpoint);
  
  });
  
  observer.observe($(".geo-current-value[latitude][longitude]")[0], {
    characterData: true,
    childList: true
  });
});



$.ajax({
    url: arcgis_script_url,
    cache: arcgis_script_cache,
    dataType: "script",
    success: function(data){
    require(["esri/portal/PortalItem",
             "esri/tasks/Locator",
             "esri/geometry/Point",
             "esri/widgets/Search",
             "esri/views/MapView", 
             "esri/WebMap",
             "esri/Graphic"],
            function (PortalItem,
                       Locator,
                       Point,
                       Search,
                       MapView,
                       WebMap,
                       Graphic) {
     
 
      clickpoint = new Point();
              
      var webmap = new WebMap({});
      
      if(!portal_map_url.length == 0 && !portal_map_id.length == 0){
        
        webmap.portalItem = new PortalItem({portal: portal_map_url,
                                            id: portal_map_id
                                           });
      
      }else{
      
        webmap.basemap = default_basemap;
      
      }
      
      mapview = new MapView({
        map: webmap,
        container: map_container,
        center: [start_lon,start_lat],
        zoom: start_zoom,
        wkid: 4326,
      });
        

      search = new Search({
        view: mapview, 
        resultGraphicEnabled: false,
        popupEnabled: true
      });
      
      search.on("select-result", function(evt){
        
        if(debug)
          console.log("The selected search result: ", JSON.stringify(evt));        
      
      });
      
      mapview.ui.add(search, map_searchbox_location);      
      
        mapview.on("click", function(evt) {
          
          if(debug)
            console.log('Click event object: '+ JSON.stringify(evt));
          
          var lat = Math.round(evt.mapPoint.latitude * latlon_factor) / latlon_factor;
          var lon = Math.round(evt.mapPoint.longitude * latlon_factor) / latlon_factor;
          
          if(debug){
            console.log('Clicked Latitude: '+ evt.mapPoint.latitude + ' (Rounded: '+ lat +')');
            console.log('Clicked Longitude: '+ evt.mapPoint.longitude + ' (Rounded: '+ lon +')');
          }
          
          if(!field_lat.length == 0)
            $('#'+ field_lat).val(lat);
          
          if(!field_lon.length == 0)
            $('#'+ field_lon).val(lon);
          
          
          search.clear();
          
          mapview.popup.clear();
          
          
          reverse_geocode(evt.mapPoint);
          
          var graphic = new Graphic({
            geometry: {
              type: marker_symbol_type,
              latitude: point.latitude,
              longitude: point.longitude,
              spatialReference: mapview.spatialReference,
            },
            symbol: {
              type: marker_symbol_click,
              color: marker_symbol_color,
              outline: {
                color: marker_symbol_outline_color,
                width: marker_symbol_outline_width,
              },
            },
          });
          
          mapview.graphics.removeAll();
          mapview.graphics.add(graphic);  
            
          
        });  
      
      });  
    }
   });



function reverse_geocode(point){
  
  if (search.activeSource) {
    
    var geocoder = search.activeSource.locator; //Defaults to ESRI World Geocode Service
    var params = {location: point};
    
    geocoder.locationToAddress(params).then(
    
      function (response) {
      
      if(debug)
        console.log('Geocoder response object: '+ JSON.stringify(response));
      
      if(debug)
        console.log('Address object for '+ JSON.stringify(point) +': ' + response.address);
      
      var location_attributes = response.attributes;
                
      // Location
      if(!field_location.length == 0)
        $('#' + field_location).val(location_attributes.LongLabel);
      
      // Address Block - Street Address
      var field_address_street = field_address_block +'_DSG0';
      
      if(!field_address_street.length == 0)
      	$('#'+ field_address_street).val(location_attributes.Address);
                
      // Address Block - Address Line 2
      var field_address_two = field_address_block +'_DSG1';
      
      if(!field_address_two.length == 0)
      	$('#'+ field_address_two).val(location_attributes.Block);
                
       // Address Block - City
       var field_address_city = field_address_block +'_DSG2';
       
       if(!field_address_city.length == 0)
       $('#'+ field_address_city).val(location_attributes.City);
                
       // Address Block - State / Province / Region
       var field_address_state_province_region = field_address_block +'_DSG3';
       
       if(!field_address_state_province_region.length == 0)
         $('#'+ field_address_state_province_region).val(location_attributes.Region + ' ' + location_attributes.Territory);
                
       // Address Block - Postal / Zip Code
       var field_address_postal_zip_code = field_address_block +'_DSG4';
       
       if(!field_address_postal_zip_code.length == 0)
         $('#'+ field_address_postal_zip_code).val(location_attributes.Postal);
                
       // Address Block - Country
       var field_address_country = field_address_block +'_DSG5';
       
       if(!field_address_country.length == 0)
         $('#'+ field_address_country).val(location_attributes.CountryCode);
                   
                
      },
      function (err) {
        
        if(debug)
          console.log('No address object found at: ' + JSON.stringify(point));
        
        if(!field_location.length == 0)
          ('#' + field_location).val("No address found.");
      });
	}
}

// Credits
// https://stackoverflow.com/questions/16619777/confused-about-mutationobserver
// https://community.esri.com/thread/235390-click-on-the-map-to-get-value-of-longitudelatitude
// https://developers.arcgis.com/javascript/latest/guide/quick-start/
// https://developers.arcgis.com/javascript/latest/guide/search-for-an-address/
// https://community.esri.com/thread/254312-graphics-for-on-map-click
// https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Search.html#event-select-result

 

Screenshot_2021-03-05 Layout Laserfiche Forms.png
1 0
replied on September 4, 2023

Hi Wes,

Would you be able to assist me? 

I need to be able to have the geo-location which has been populated with table data to show up on the embedded map.

I want to use it as a verification of the table data and make the map read-only.

Would you be able to give me an example of how I can do this?

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.