0

I'm tring to fill a javascript array with lat longs that I can use to put markers on a map from my model but it's riddled with errors and I'm not sure why.

<div id="map"></div>
<script>

    var map,
    points = [];

    @foreach (var a in Model) {
        //Error: The name 'points' does not exist in the current context
                   //Error: ) expected ; expected (at front and end brackets)
        points.push({ lat: @a.Lat, lng: @a.Lon });
    }

    function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
            center: { lat: -34.397, lng: 150.644 },
            zoom: 8
        });
        //Error: The name 'points' does not exist in the current context
        @foreach (var p in points) {
            var marker = new google.maps.Marker({ position: p });
            //Error: The name 'marker' does not exist in the current context
            //Error: The name 'map' does not exist in the current context
            marker.setMap(map);
        }
    }

</script>
<script src="https://maps.googleapis.com/maps/api/js?key=MyKey&callback=initMap"
    async defer></script>

Model

public class Vehicle
{
    [Key]
    public int ID { get; set; }
    public decimal Lon { get; set; }
    public decimal Lat { get; set; }
    public string VehType { get; set; }
    public string Driver { get; set; }
}
Mr.Smithyyy
  • 2,157
  • 12
  • 49
  • 95
  • 4
    `@foreach` is razor code. It is evaluated on the server before its sent to the view. `points` is a client side javascript variable which does not even exist at that point - its not in scope. –  Nov 20 '15 at 00:44
  • 1
    And I have just noticed this is a repeat of your [last question](http://stackoverflow.com/questions/33816493/using-javascript-arrays-filled-with-model-data-to-add-google-map-markers). Please delete one or the other –  Nov 20 '15 at 00:49
  • So what would the solution be? – Mr.Smithyyy Nov 20 '15 at 01:02
  • You just need to assign you Model to a javascript array, for example `var points = @Html.Raw(Json.Encode(Model))`. The first `foreach` is not required and the second needs to replace with a javascript loop. –  Nov 20 '15 at 01:09
  • If your show your model (and delete the other question) I can add an answer. –  Nov 20 '15 at 01:10
  • I've added the model and deleted the previous question. – Mr.Smithyyy Nov 20 '15 at 01:13
  • No problem, I've been pulling my hair out for hours over this, whats a few more minutes 8) – Mr.Smithyyy Nov 20 '15 at 01:19

2 Answers2

1

@foreach() is razor code. It is evaluated on the server before its sent to the view. points is a client side javascript variable which does not exist at that point - its not in scope. Instead, you can assign your model to a javascript array using @Html.Raw(Json.Encode(Model). Your script would then be

var model = @Html.Raw(Json.Encode(Model)); // ignore the annoying 'syntax error'
points = [];
$.each(model, function (index, item) {
    points.push({ lat: item.Lat, lng: item.Lon})
})
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: { lat: -34.397, lng: 150.644 },
        zoom: 8
    });
    for (var i = 0; i < points.length; i++) {
        var marker = new google.maps.Marker({ position: points[i] });
        marker.setMap(map);
    }
}
  • That fixes the top part, but what about the second for loop that places the markers? – Mr.Smithyyy Nov 20 '15 at 01:41
  • That's some progress! I'm not seeing markers still but at least the map is working and I'm not getting any syntax errors. – Mr.Smithyyy Nov 20 '15 at 01:49
  • Actually markers just showed up, thank you for all the help! – Mr.Smithyyy Nov 20 '15 at 01:53
  • Quick question, do you know how I would set the initial coordinates to the first pair in the points array? – Mr.Smithyyy Nov 20 '15 at 01:55
  • You can get the first set of coordinates using `var initial = points[0];` but I'm not sure what you mean by _"set the initial coordinates"_ –  Nov 20 '15 at 01:57
  • in the `initMap()` function you set the initial center of the map. So I would like to set it to the first pair of lat lng coordinates. – Mr.Smithyyy Nov 20 '15 at 01:58
1

Yes, because inside the @foreach loop, it's C# code, not Javascript. And your points is a Javascript variable, so you cannot just place it like that.

To fix this, you have 2 ways:

  1. Wrap it within <text> tag:

<text>points.push({ lat: @a.Lat, lng: @a.Lon });</text>

  1. In case your Javascript only has one line, you can use @: like this:

@:points.push({ lat: @a.Lat, lng: @a.Lon });

Triet Doan
  • 11,455
  • 8
  • 36
  • 69
  • Again, this is server side code - `points` does not exist so the same error will occur. –  Nov 20 '15 at 01:47
  • Are you sure? I'm sure wrapping it inside `` tag will solve your problem. Please take a look at [this answer](http://stackoverflow.com/questions/5614941/mix-razor-and-javascript-code/5614995#5614995) – Triet Doan Nov 20 '15 at 01:48
  • You correct, it will work despite the multiple error the RazorTemplateEngine reports, and if the values are numbers only (otherwise you have to determine what to quote and what not quote). –  Nov 20 '15 at 02:06
  • @StephenMuecke Razor has always had problems with JS output and many times it's just parser errors but the page will compile just fine. – jamesSampica Nov 20 '15 at 03:40