2

So, I'm trying to pass a list of strings from my apex class to my vf page, to use it on google maps API. The problem is that I can't pass the list containing my data. Here's my code:

Class

public with sharing class MapAccountExtension
{
    public List<Account> acc {get;set;}
    public String temp {get;set;}
    public List<String> location {get;set;}
    public Integer acclength {get;set;}

    public MapAccountExtension(ApexPages.StandardController controller) {
    }

    public MapAccountExtension()
    {
        acc = [SELECT Name, BillingStreet,BillingCity,BillingCountry FROM Account];
        List<String> location = new List<String>();
        system.debug(acc);
        acclength = acc.size();
        system.debug(acclength);
        for (integer i = 0; i <acclength ;i++)
        {
            temp = null;
            temp = acc[i].Name + ' , ' + acc[i].BillingStreet + acc[i].BillingCity + ' , ' + acc[i].BillingCountry;
            location.Add(temp); 
        }

        system.debug(location);
    }

}

VF Page with script

<apex:page standardController="Account" extensions="MapAccountExtension">
<head> 
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> 
    <script type="text/javascript"/> 
</head> 
<body>
<div id="map" style="width: 800px; height: 600px;"></div>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript">
alert ('1st' + '{!location}');
var locationArray = new Array();
locationArray= '{!location}');
alert('2nd' + locationArray);
var delay = 100;
var infowindow = new google.maps.InfoWindow();
var latlng = new google.maps.LatLng(21.0000, 78.0000);
var mapOptions = {
    zoom: 5,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
var geocoder = new google.maps.Geocoder(); 
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var bounds = new google.maps.LatLngBounds();

function geocodeAddress(address, next) {
geocoder.geocode({address:address}, function (results,status)
    { 
        if (status == google.maps.GeocoderStatus.OK) {
        var p = results[0].geometry.location;
        var lat=p.lat();
        var lng=p.lng();
        createMarker(address,lat,lng);
      }
      else {
          if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
          nextAddress--;
          delay++;
        } else {
                       }   
        }
      next();
    }
    );
}
function createMarker(add,lat,lng) {
  var contentString = add;
  var marker = new google.maps.Marker({
    position: new google.maps.LatLng(lat,lng),
    map: map,
          });

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString); 
    infowindow.open(map,marker);
   });

   bounds.extend(marker.position);

}
var nextAddress = 0;
function theNext() {
  if (nextAddress < locationArray.length) {
    setTimeout('geocodeAddress("'+locationArray[nextAddress]+'",theNext)', delay);
    nextAddress++;
  } else {
    map.fitBounds(bounds);
  }
}
theNext();

</script>
</body>
</apex:page>

If i set the location string passed to the api manually (created on javascipt), it resolves fine, so it really is that I cant pass the string to the javascript. What I'm doing wrong?

UPDATED: working sample

VF Page

<apex:page standardController="Account" extensions="MapAccountExtension">
  <head> 
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> 
    <script type="text/javascript"/> 
</head> 
<body>
  <div id="map" style="width: 800px; height: 600px;"></div>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false">
 </script> 
 <script type="text/javascript">

  var locationString = {!locationsJson};

  var delay = 100;
  var infowindow = new google.maps.InfoWindow();
  var latlng = new google.maps.LatLng(39,-8);
  var mapOptions = {
    zoom: 6,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  var geocoder = new google.maps.Geocoder(); 
  var map = new google.maps.Map(document.getElementById("map"), mapOptions);
  var bounds = new google.maps.LatLngBounds();

  function geocodeAddress(address, next) {
    geocoder.geocode({address:address}, function (results,status)
      { 
         if (status == google.maps.GeocoderStatus.OK) {
          var p = results[0].geometry.location;
          var lat=p.lat();
          var lng=p.lng();
          createMarker(address,lat,lng);
        }
        else {
           if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
            nextAddress--;
            delay++;
          } else {
                        }   
        }
        next();
      }
    );
  }
 function createMarker(add,lat,lng) {
   var contentString = add;
   var marker = new google.maps.Marker({
     position: new google.maps.LatLng(lat,lng),
     map: map,
           });

  google.maps.event.addListener(marker, 'click', function() {
     infowindow.setContent(contentString); 
     infowindow.open(map,marker);
   });

   bounds.extend(marker.position);

 }

  var nextAddress = 0;
  function theNext() {
    if (nextAddress < locationString.length) {
      setTimeout('geocodeAddress("'+locationString[nextAddress]+'",theNext)', delay);
      nextAddress++;
    } else {
      map.fitBounds(bounds);
    }
  }
  theNext();

</script>
</body>
</apex:page>

Class

public with sharing class MapAccountExtension {

    public List<Account> acc {get;set;}
    public String temp {get;set;}
    public List<String> location {get;set;}
    public Integer acclength {get;set;}

    public MapAccountExtension(ApexPages.StandardController controller) {
    }

    public String locationsJson {
        get {
            String[] locations = new String[] {};
            for (Account a : [
                    SELECT Name, BillingStreet,BillingCity,BillingCountry
                    FROM Account
                    ORDER BY Name
                    LIMIT 1000
                    ]) {
                locations.add(a.Name
                        + ' , ' + a.BillingStreet
                        + ' ' + a.BillingCity
                        + ' , ' + a.BillingCountry
                        );
            }
            for (integer i= 0;i<locations.size();i++)
            {
                locations[i] = locations[i].replaceAll('\\n',' ');
            }
            return JSON.serialize(locations);
        }

    }
}
1

As well as how the location array is build (see Vamsi's answer) there is a problem in how the Apex array is turned into valid JavaScript. To get the embedded commas correctly escaped and ensure that the string rendered into the page in array in JavaScript (i.e. var locationArray = ['abc', 'def'];) you can use JSON formatting:

public with sharing class MapAccountExtension {

    public String locationsJson {
        get {
            String[] locations = new String[] {};
            for (Account a : [
                    SELECT Name, BillingStreet,BillingCity,BillingCountry
                    FROM Account
                    ORDER BY Name
                    LIMIT 1000
                    ]) {
                locations.add(a.Name
                        + ' , ' + a.BillingStreet
                        + ' , ' + a.BillingCity
                        + ' , ' + a.BillingCountry
                        );
            }
            return JSON.serialize(locations);
        }
    }
}

JSON is the native JavaScript format for representing data structures including arrays and objects.

Given the above Apex, in your JavaScript the assignment can be just this:

var locationArray = {!locationsJson};

When you think you have the code right, use your browser's "Inspect Element" to check the formatting and also check that there are no JavaScript errors in the JavaScript Console. (See How do I start to debug my own Visualforce/JavaScript?)

  • Did the trick! Will update the first post with the working code. Thanks Keith! – danielpm May 25 '15 at 16:36
  • 1
    You should probably add JSINHTMLENCODE or some othe type of encoding into your locationArray merge. Security scanner will flag the lack thereof. – Adrian Larson May 25 '15 at 16:53
1

You have declared a local variable inside the controller with the same name and populating it instead of populating the class level variable.

if you change that to use the class level variable, it should work fine.

line number 5 :

public List<String> location {get;set;}

and then again inside your constructor at line 14 :

   List<String> location = new List<String>();

you should remove this second one inside the constructor and try..

  • But Vamsi, my "location" varible isn't a class level variable? I'm declaring it on the class, not in the method – danielpm May 25 '15 at 11:13
  • just updated my answer, pls chk – Vamsi Krishna May 25 '15 at 11:20
0

Actually using this '{!location}' for getting list in script dosen't return as a list but as a string in a format like: [value1,value2,value3...]

So, you have to split the string and convert it into an array:

var locationString = '{!location}';
var locationArray = new Array();
locationArray = locationString.substring(1,namelist.length-1).split(',');

Hope this may help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.