Using VueJS Single File Components can cause issues with the example code for "Custom Popups" in the Google Maps API

Trying to implement a unique Google Maps popup following the provided documentation.

After copying and pasting the official Google example code into a VueJS jsFiddle, the custom marker functions correctly as intended. It remains in the designated area even when panning across the map. You can view the jsFiddle here.

"Hello this is me" will always maintain its initial position regardless of map movement. This is the desired outcome.

https://i.sstatic.net/613d9.png

However, upon transferring the code into a VueJS single file component, the marker fails to stay in the correct spot. Instead, it consistently appears at the center of the whole map irrespective of panning (as depicted below). Moreover, the styling of the Popup breaks down. View the sandbox showcasing the issue (Refer to HelloWorld.vue component)

https://i.sstatic.net/zSR8S.png

The code present in my Single File Component is given below (almost identical to the jsFiddle).

Why am I experiencing inconsistent outcomes and how can I modify the Single File Component to achieve the same result as the jsFiddle?

<template>
    <div>
        <div id="map"></div>
        <div id="content">
            Hello this is me
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                map: "",
                popup: "",
                Popup: "",
            };
        },
        methods: {
            definePopupClass() {
                /**
                * A customized popup on the map.
                * @param {!google.maps.LatLng} position
                * @param {!Element} content
                * @constructor
                * @extends {google.maps.OverlayView}
                */
                this.Popup = function(position, content) {
                    this.position = position;

                    content.classList.add('popup-bubble-content');

                    var pixelOffset = document.createElement('div');
                    pixelOffset.classList.add('popup-bubble-anchor');
                    pixelOffset.appendChild(content);

                    this.anchor = document.createElement('div');
                    this.anchor.classList.add('popup-tip-anchor');
                    this.anchor.appendChild(pixelOffset);

                    // Optionally stop clicks, etc., from bubbling up to the map.
                    this.stopEventPropagation();
                };
                // NOTE: google.maps.OverlayView is only defined once the Maps API has
                // loaded. That is why Popup is defined inside initMap().
                this.Popup.prototype = Object.create(google.maps.OverlayView.prototype);

                /** Called when the popup is added to the map. */
                this.Popup.prototype.onAdd = function() {
                    this.getPanes().floatPane.appendChild(this.anchor);
                };

                /** Called when the popup is removed from the map. */
                this.Popup.prototype.onRemove = function() {
                    if (this.anchor.parentElement) {
                        this.anchor.parentElement.removeChild(this.anchor);
                    }
                };

                /** Called when the popup needs to draw itself. */
                this.Popup.prototype.draw = function() {
                    var divPosition = this.getProjection().fromLatLngToDivPixel(this.position);
                    // Hide the popup when it is far out of view.
                    var display =
                    Math.abs(divPosition.x) < 4000 && Math.abs(divPosition.y) < 4000 ?
                    'block' :
                    'none';

                    if (display === 'block') {
                        this.anchor.style.left = divPosition.x + 'px';
                        this.anchor.style.top = divPosition.y + 'px';
                    }
                    if (this.anchor.style.display !== display) {
                        this.anchor.style.display = display;
                    }
                };

                /** Stops clicks/drags from bubbling up to the map. */
                this.Popup.prototype.stopEventPropagation = function() {
                    var anchor = this.anchor;
                    anchor.style.cursor = 'auto';

                    ['click', 'dblclick', 'contextmenu', 'wheel', 'mousedown', 'touchstart',
                    'pointerdown']
                    .forEach(function(event) {
                        anchor.addEventListener(event, function(e) {
                            e.stopPropagation();
                        });
                    });
                };
            }
        },
        mounted() {
            this.$nextTick(() => {
                this.definePopupClass();
                this.map = new google.maps.Map(document.getElementById('map'), {
                    center: {lat: -33.9, lng: 151.1},
                    zoom: 10,
                });

                this.popup = new this.Popup(
                    new google.maps.LatLng(-33.866, 151.196),
                    document.getElementById('content'));
                this.popup.setMap(this.map);
            });
        }
    };
</script>

<style scoped>

    /* Always set the map height explicitly to define the size of the div
    * element that contains the map. */
    #map {
        height: 500px;
        width: 500px;
    }
    /* Optional: Makes the sample page fill the window. */
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    /* The location pointed to by the popup tip. */
    .popup-tip-anchor {
        height: 0;
        position: absolute;
        /* The max width of the info window. */
        width: 200px;
    }
    /* The bubble is anchored above the tip. */
    .popup-bubble-anchor {
        position: absolute;
        width: 100%;
        bottom: /* TIP_HEIGHT= */ 8px;
        left: 0;
    }
    /* Draw the tip. */
    .popup-bubble-anchor::after {
        content: "";
        position: absolute;
        top: -1px;
        left: 0;
        /* Center the tip horizontally. */
        transform: translate(-50%, 0);
        /* The tip is a https://css-tricks.com/snippets/css/css-triangle/ */
        width: 0;
        height: 0;
        /* The tip is 8px high, and 12px wide. */
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-top: /* TIP_HEIGHT= */ 8px solid white;
    }
    /* The popup bubble itself. */
    .popup-bubble-content {
        position: absolute;
        top: 0;
        left: 0;
        transform: translate(-50%, -100%);
        /* Style the info window. */
        background-color: white;
        padding: 5px;
        border-radius: 3px;
        font-family: sans-serif;
        overflow-y: auto;
        max-height: 60px;
        box-shadow: 0px 2px 10px 1px rgba(0,0,0,0.5);
    }
</style>

Answer №1

This issue arose due to my utilization of scoped styles within the Single File Component illustration. By simply removing the scoped attribute from the style tag, the problem was successfully resolved.

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

Focusing on particular jQuery elements that share the same class names

I am facing an issue with dynamically generated divs that share the same class names. When I hover over the parent div (myDiv), I want to trigger an event and add a class to the myDiv child button. However, when I click on the parent div, I want to unbind ...

Alter data in MongoDB based on specific circumstances

Currently, I am utilizing node.js and mongoose for a project. The task at hand involves updating database information only if the required field either does not exist in the database or its value is less than 'x'. Specifically, this pertains to ...

Ways to alert user prior to exiting page without initiating a redirect

I have a feature on my website where users can create and edit posts. I want to notify them before leaving the page in these sections. Here's how I can accomplish that: //Add warning only if user is on a New or Edit page if(window.location.href.index ...

Issues with Angular ng-model-options not working properly in Internet Explorer

Is there a way to submit a form on keypress/enter while using ng-model-options="{updateOn: 'submit'}" Here is the template: <form ng-model-options="{ updateOn: 'submit' }"> <input type="submit" value="submit" style="visib ...

Setting up a Laravel 7 and Vue single page application on a shared hosting environment

Hello, I'm facing an issue with my application that has a Vue front-end and Laravel 7 back-end. The problem is that I am unable to redirect to the login page and instead, it shows a blank screen. All the Vue files are stored in the resource/js folder ...

Delete an item from an array when a dropdown selection is made

When dealing with Angular 8, I encountered a logic issue. There are two drop-down menus: First Drop-down The options in the first menu are populated from an array of objects Example Code, ts: {rs_id: "a5f100d5-bc88-4456-b507-1161575f8819", ...

The method by which npmjs.com evaluates the quality of code

After we release a package on npm, it provides us with insights such as popularity, quality, and maintenance on the search page (Refer to the example image below). I am particularly curious about how npm determines the quality metric. Any insights would be ...

Error encountered while running `vue-cli-service build`: validation error for new workbox-webpack-plugin configurations

Considering the contents of vue.config.js: module.exports = { pwa: { name: 'My App', ... workboxPluginMode: 'InjectManifest', workboxOptions: { swSrc: 'src/sw.js', //and I use "sw.js" in my registerSe ...

ReactJS incorporates multiple CSS files

I am currently working on developing a Single Page Application using ReactJS. However, I am facing an issue with styling. Currently, I have created 3 different pages (with the intention of adding more in the future), each having its own CSS file that is im ...

What is the best way to load the route calculation dynamically?

I am struggling with calculating the Google Maps route dynamically. The console shows an error stating that 'calcularRuta' is not defined: Uncaught ReferenceError: calcularRuta is not defined at HTMLInputElement.onclick (index.html:1) Despi ...

Attempting to modify the color of a selected Three.js object causes all objects in the scene to have their colors altered

For example, check out this JSFiddle link. The interesting part occurs during the mousedown event: var hits = raycaster.intersectObjects( [object1, object2, object3] ); if ( hits.length > 0 ) { console.log(hits[ 0 ].object) hits[ 0 ].object.m ...

Click on the print icon in the modal window

I have been working on a receipt generator for a client. The client can add payment receipts using the "Add" button, and upon submission, they have the option to convert it to PDF or print it. However, there seems to be an issue with printing as the text f ...

Ensure that the promise is fulfilled only if a specific condition is met

I have a complex if-else condition in my code that includes different promises. Once the logic determines which condition to enter and executes the corresponding promise, I need to ensure that a final promise is always executed. if (a < 5) { vm.pr ...

Creating dynamic animations for your elements with AJAX

How can I apply animation to an element as soon as it appears? I want others with the same properties to remain unaffected. Here is my approach: $.each(data, function(i, obj) { if(obj['Ping'] == "FALSE"){ ...

Coloring a table in vue.js based on performance rankings

I'm facing an issue with sorting my data performance in vue js. Here is the script I have created so far: <template> <div> <div class="row"> <h2> Campaign Performance </h2> <table class=&q ...

What could be the reason why readyState is not equal to 4?

I've been trying to figure out how to use Ajax to fetch data from a database, but I'm encountering some issues... The problem arises when I submit the query and nothing appears on the screen... I understand that this issue is related to the read ...

What to do when encountering a problem with HTML, CSS, and JS while loading a webpage from an SD card to a WebView

I am facing an issue while loading an HTML file from the SD card to a webview. The problem is that the CSS, images, and videos are not loading properly in the webview. Compatible with Android 4.4 KitKat and Chrome version Not compatible with versions belo ...

Retrieve the image by its unique identifier while viewing a preview of the image before it is uploaded

Below is the script I am using to preview an image before it is uploaded. The HTML structure looks like this: <div> <img id="image" src="#"> </div> <input type="file" accept="image/gif, image/jpeg, image/png" onchange="readURL(th ...

What is the purpose of Access-Control-Allow-Headers in an HTTP response and why is it important to include it?

I've been working through a tutorial on using express and have come across the following routes: module.exports = function(app) { app.use(function(req, res, next) { res.header( "Access-Control-Allow-Headers", "x-ac ...

Adding items to an array retrieved from JSON

My goal is to merge 3 different Facebook feeds into a single object called "item." Each item includes the post creation time and the JSON data itself. However, I'm facing an issue where only 5 items are displayed when I check the log, even though ther ...