AngularJS Infowindow Button

Within my map, I have designated various locations with markers. Once a marker is clicked, an infowindow appears containing the place's name and a button. To capture these places in an array when the button within the infowindow is clicked, I require a function.

Below is the code snippet:

$scope.routes = [];
locations = data;
$scope.map = new google.maps.Map(document.getElementById('map'), {
  zoom: 11,
  center: new google.maps.LatLng(12.9716, 77.5946),
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

$scope.infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
  marker = new google.maps.Marker({
    icon: {
      url: 'img/map-marker.png',
      scaledSize: new google.maps.Size(25, 25)
    },
    position: new google.maps.LatLng(locations[i].Latitude, locations[i].Longitude),
    map: $scope.map
  });

  google.maps.event.addListener(marker, 'click', (function(marker, i) {
    return function() {
      var content1 = locations[i].Name + '<button class="btn btn-success" ng-click="AddLoc(\'' + locations[i].Name + '\');">Add</button>';
      var content = $compile(content1)($scope);
      $scope.infowindow.setContent(content[0]);
      $scope.infowindow.open($scope.map, marker);
    }
  })(marker, i));
}
$scope.AddLoc = function(x) {
  $scope.routes.push(x);
  alert($scope.routes);
}

However, upon clicking a marker while running the code, it throws an error.

An exception occurred at line 31, column 318 in http://ajax.googleapis.com ajax/libs/angularjs/1.5.8/angular.min.js

0x800a139e - JavaScript runtime error: [jqLite:nosel] http://errors.angularjs.org/1.5.8/jqLite/nosel

I would greatly appreciate any assistance or guidance in resolving this issue.

Answer №1

As per the angular.js source code, the compile function creates a jqLite element. When dealing with HTML strings, it is considered valid only if enclosed within tags:

if (argIsString && element.charAt(0) !== '<') {
  throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
}

In summary, compilation fails when representing an HTML string in this format abc:

var t = $compile("abc")($scope);  //fails

If wrapped within tags, such as <div>abc</div>, the compilation succeeds:

var t = $compile("<div>abc</div>")($scope);  //succeed 

Solution

Enclose tooltip HTML content within a container div element.

Replace this line:

var content1 = locations[i].Name + '<button class="btn btn-success" ng-click="AddLoc(\''+locations[i].Name+'\');">Add</button>';

with

var content1 = '<div>' + locations[i].Name + '<button class="btn btn-success" ng-click="AddLoc(\''+locations[i].Name+'\');">Add</button>' + '</div>';

Demo

angular.module('mapApp', [])
  .controller('mapCtrl', function($scope, $rootScope, $compile) {
    $scope.routes = [];
    $scope.locations = [{
        Name: 'Sydney',
        Latitude: -33.873033,
        Longitude: 151.231397
      },
      {
        Name: 'Melbourne',
        Latitude: -37.812228,
        Longitude: 144.968355
      }
    ];

    $scope.map = new google.maps.Map(document.getElementById('map'), {
      zoom: 3,
      center: new google.maps.LatLng(-38.363, 131.044),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    $scope.infowindow = new google.maps.InfoWindow();
    var marker, i;
    for (i = 0; i < $scope.locations.length; i++) {
      marker = new google.maps.Marker({
        //icon: { url: 'img/map-marker.png', scaledSize: new google.maps.Size(25, 25) },
        position: new google.maps.LatLng($scope.locations[i].Latitude, $scope.locations[i].Longitude),
        map: $scope.map
      });

      google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          var tooltipHtml = '<div>' + $scope.locations[i].Name + '<button class="btn btn-success" ng-click="addLoc(\'' + $scope.locations[i].Name + '\');">Add</button>' + '</div>';
          var elTooltip = $compile(tooltipHtml)($scope);
          $scope.infowindow.setContent(elTooltip[0]);
          $scope.infowindow.open($scope.map, marker);
        }
      })(marker, i));
    }
    $scope.addLoc = function(x) {
      $scope.routes.push(x);
    };
  });
html,
body {
  height: 400px;
  margin: 0;
  padding: 0;
}

#map {
  height: 400px;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.1/lodash.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<link type="text/css" rel="stylesheet" href="style.css">
<div ng-app="mapApp" ng-controller="mapCtrl">
  <pre style="width: 30%; height: 400px; overflow-y: scroll; float:left;">
       {{routes | json}} 
    </pre>
  <div id="map" style="float:left; width:60%;"></div>
</div>

Answer №2

The self-invoking function seems quite questionable...

Since the marker is already within the loop scope, I don't believe it needs to be included as a parameter

Perhaps try simplifying it like this:

google.maps.event.addListener(marker, 'click', function(i) { 
  var content1 = locations[i].Name + '<button class="btn btn-success" ng-click="AddLoc(\''+locations[i].Name+'\');">Add</button>';
  var content = $compile(content1)($scope);

  $scope.infowindow.setContent(content[0]);
  $scope.infowindow.open($scope.map, marker);
}); 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Setting up Jest

I'm currently attempting to integrate the Jest Testing framework into my React Native project. Unfortunately, I am encountering an error message: Failed to retrieve mock metadata: /Users/me/Documents/Development/project/node_modules/global/window.js ...

Issue encountered with the openpgpjs example: `'The function openpgp.encrypt is not defined'`

I encountered an issue with the 'openpgp.encrypt is not a function' error while attempting to follow the sample provided on the openpgp.js github page: https://github.com/openpgpjs/openpgpjs/blob/master/README.md#getting-started After following ...

Utilizing PathLocationStrategy in Angular 2 with Laravel and .htaccess configurations

I am facing challenges while configuring the .htaccess file for Laravel and Angular 2. Whenever I refresh the browser window, I encounter a 404 error page and I want to avoid using the html5 hashbang strategy. I am utilizing routing from both Angular 2 and ...

Passing data from an API in Vue.js to a different page

I'm a beginner with Vue Js and I'm looking for guidance on how to send data between two components. Currently, I am working on a Vue app that fetches a list of users from an API and displays them. My goal is to transfer data between these compone ...

In Firefox, an error occurs when Window.getComputedStyle does not adhere to the Element interface

After successfully appending data to the HTML element using the code below: $("#bookListDiv").append(data.HTMLString); I wanted to enhance the display by adding a fadein animation. So, I made some adjustments to achieve this effect: $(data.HTMLString).h ...

Is your form complete?

Is there a way to determine if all required fields in the current form are correctly filled in order to disable/enable navigation? Are there any specific properties or JQuery functions that can be used to check for form completion status? ...

What is the best way to display a button only during office hours from 9am to 5pm using React.js or JavaScript?

If I want a button to only be visible from 9am to 5pm, how can this be achieved where the button is hidden outside of that time frame? ...

jQuery: Modifying tags is a one-time deal

I am trying to create a feature where a <p> tag becomes editable when clicked. However, I am encountering an issue - it can only be edited once. Upon a second click, an error message appears in the console. You can view the fiddle demonstrating this ...

Tips for referencing an object with a semicolon included

I've encountered an issue while working with AngularJS and the WordPress Rest API. When making a get request that returns an object, I must use the '?embed' parameter to access another object called _embedded in order to retrieve a featured ...

JavaScript - Separate Artist and Title

In the code snippet below, I am using a Parser script to extract metadata from a live streaming radio station: const Parser = require('../src'); const radioStation = new Parser('http://stream.com/live_32.aac'); radioStation.on(' ...

Implementing promises in Node JS Express

I am new to promises and trying to understand how they function. Here are my initial questions: When a request is handled in a route function, does it wait for all promises? Does using a promise or callback create a new scope where execution continues ...

I'm having trouble getting my .click method to work with the <div id=menuButton>. Can anyone help me figure out why this is happening?

Here is the HTML code I created for a dropdown menu. Initially, in the CSS file, the menu is set to display: none; <!doctype html> <html> <head> <title>DropDown Menu</title> <link rel="stylesheet" href="normalize ...

Challenges in developing complex single-page applications

Currently, I am in the process of developing an extensive single-page web/javascript application that is going to be quite large. The technologies I am utilizing include ASP.NET MVC4, jquery, knockout.js, and amplify.js. One obstacle I am encountering is ...

Analyzing the original data form versus the modified data

I'm dealing with a form in React that utilizes react-hook-form and the useFieldArray method for adding dynamic steps. The challenge I'm facing is how to compare the original data passed to the form with the edited data, in order to make correspon ...

Associate JSON sub-string with corresponding main parent

I am working with a JSON string that is generated from an API. [{"categories":{"category":{"id":"1","Name":"fruit"}}},{"categories":{"category":{"id":"2","Name":"veg"}}},{"products":{"product":{"id":"1","Name":"fruit"}}},{"products":{"product":{"id":"2"," ...

Mobile Size Setting

Could someone please explain to me why when I test this code on Google Chrome using the mobile emulator for Galaxy S3, it displays the correct size (640x360), but when I try to load it on my actual Galaxy S5 or any other device, the size is different from ...

Guide on embedding internet audio onto an HTML webpage

I'm currently working on adding sounds and music to my program. The code that I have works perfectly when the audio files are downloaded onto my computer. However, I am looking for a way to play these sounds directly from the internet without needing ...

Adjusting camera orientation and field of view using trackball manipulation controls in THREEJS

Manually setting the position and fov of the perspective camera in THREE.JS is working as expected for me. However, when I try to interact with the scene later using the TrackBall Controls, it just shows a black screen with no errors. Check out this JS Fi ...

What steps should be followed to execute this moment.js code in an Angular.js controller using Node.js?

I am trying to adapt the following node.js code that uses moment.js into an AngularJS controller: var myDate = new Date("2008-01-01"); myDate.setMonth(myDate.getMonth() + 13); var answer = moment(myDate).format('YYYY-MM-DD'); To achieve this, I ...

Press Button to create cookie and store it in Drupal 7

I am currently working on my Drupal 7 local website, which features an article and a popup on the homepage leading to that article. Within the article, there is a button that I want to serve as a way for users to dismiss the initial popup permanently. My i ...