Transform leaflet marker plugin into Typescript format

I recently discovered a leaflet extension that conceals map markers if they fall outside the boundaries of the current view map.

import L from 'leaflet';

L.Marker.MyMarker= L.Marker.extend({}).addInitHook(function (this: ILazyMarker) {
    this.on(
        'add',
        function (this: ILazyMarker) {
            this._updateIconVisibility = function (this: ILazyMarker) {
                var map = this._map,
                    isVisible = map.getBounds().contains(this.getLatLng()),
                    wasVisible = this._wasVisible,
                    icon = this._icon,
                    iconParent = this._iconParent,
                    shadow = this._shadow,
                    shadowParent = this._shadowParent;

                // keep track of parent of icon
                if (!iconParent) {
                    iconParent = this._iconParent = icon.parentNode;
                }
                if (shadow && !shadowParent) {
                    shadowParent = this._shadowParent = shadow.parentNode;
                }

                // remove or add to DOM based on visibility change
                if (iconParent != null && isVisible != wasVisible) {
                    if (isVisible) {
                        iconParent.appendChild(icon);
                        if (shadowParent != null && shadow) {
                            shadowParent.appendChild(shadow);
                        }
                    } else {
                        iconParent.removeChild(icon);
                        if (shadowParent != null && shadow) {
                            shadowParent.removeChild(shadow);
                        }
                    }

                    this._wasVisible = isVisible;
                }
            };

            // update icon visibility on map size change
            this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
            this._updateIconVisibility();
        },
        this,
    );
});

The functionality works flawlessly, but I prefer using a Typescript class for uniformity across my project. Below is my attempt at converting it:

import L from 'leaflet';

export default class MyMarker extends L.Marker {
    _wasVisible!: boolean;
    _icon!: any;
    _shadowParent!: any;
    _iconParent!: any;

    constructor(latlng: L.LatLngExpression, options?: L.MarkerOptions) {
        super(latlng, options);
    }

    onAdd(): this {
        this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
        this._updateIconVisibility();
        return this;
    }

    _updateIconVisibility() {
        var map = this._map,
            isVisible = map.getBounds().contains(this.getLatLng()),
            wasVisible = this._wasVisible,
            icon = this._icon,
            iconParent = this._iconParent,
            shadow = this._shadow,
            shadowParent = this._shadowParent;

        // remember parent of icon
        if (!iconParent) {
            iconParent = this._iconParent = icon.parentNode;
        }
        if (shadow && !shadowParent) {
            shadowParent = this._shadowParent = shadow.parentNode;
        }

        // add/remove from DOM on change
        if (iconParent != null && isVisible != wasVisible) {
            if (isVisible) {
                iconParent.appendChild(icon);
                if (shadowParent != null && shadow) {
                    shadowParent.appendChild(shadow);
                }
            } else {
                iconParent.removeChild(icon);
                if (shadowParent != null && shadow) {
                    shadowParent.removeChild(shadow);
                }
            }

            this._wasVisible = isVisible;
        }
    }
}

However, when trying to use this marker class, I encounter an error for each marker added and the map fails to render:

TypeError: Cannot read property 'parentNode' of undefined
    at MyMarker._updateIconVisibility (leaflet-my-marker.ts:78)
    at MyMarker.onAdd (leaflet-my-marker.ts:63)
    at MyMarker._layerAdd (leaflet-src.js:6567)
    at NewClass.whenReady (leaflet-src.js:4428)
    at NewClass.addLayer (leaflet-src.js:6629)
    at NewClass.addLayer (leaflet-src.js:6780)
    at VueComponent.addLayer (LLayerGroup.js:164)
    at VueComponent.FirecamMarker.mounted (MyMarker.vue?6277:99)
    at invokeWithErrorHandling (vue.runtime.esm.js:1854)
    at callHook (vue.runtime.esm.js:4219)

Answer №1

According to the "Law of Code Dilemma": No matter how much time you spend troubleshooting a coding issue, the solution will only reveal itself once you seek help on an online forum.

I dedicated several days to dissecting this problem... only to find the answer miraculously shortly after seeking assistance on an online platform. It turns out, I needed to invoke the super's onAdd method within my own onAdd method, as demonstrated below:

onAdd(): this {
    super.onAdd(this._map);
    this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
    this._updateIconVisibility();
    return this;
}

The reason for this oversight was that the original code referenced `addInitHook()` instead of `setInitHook()`, hence the confusion.

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

Steps to filter types by a singular property assessment

export type HalfSpin = { halfspin: string } export type FullSpin = { fullspin: string } export type SpinType = | HalfSpin | FullSpin export function isHalfSpin(_: SpinType) ...

Displaying various pop-up notifications upon clicking a table element

I am completely new to VueJS and I'm currently working on populating a table with various columns, one of which contains a button that triggers the opening of a modal. There are three different types of modals that can be opened based on certain condi ...

The Gulp task is stuck in an endless cycle

I've set up a gulp task to copy all HTML files from a source folder to a destination folder. HTML Gulp Task var gulp = require('gulp'); module.exports = function() { return gulp.src('./client2/angularts/**/*.html') .pipe( ...

Is there a way to utilize the child component's method?

I am looking to access a child component's method from the parent in Vue.js. To achieve this, I plan on using $refs. Code Example: <template> <div>Parent!</div> </template> Script: <script> Vue.component('c ...

I lost my hovering tooltip due to truncating the string, how can I bring it back in Angular?

When using an angular ngx-datatable-column, I added a hovering tooltip on mouseover. However, I noticed that the strings were too long and needed to be truncated accordingly: <span>{{ (value.length>15)? (value | slice:0:15)+'..':(value) ...

Monitor a universal function category

Trying to implement a TypeScript function that takes a single-argument function and returns a modified version of it with the argument wrapped in an object. However, struggling to keep track of the original function's generics: // ts v4.5.5 t ...

How can I prevent my Vue.js application from losing focus when navigating to different components?

I am encountering an issue with my Vue.js app where the focus is lost when changing routes. Initially, when the site loads, the first element of the header component is correctly in focus as desired. However, when navigating to a different link on the site ...

Avoiding caching when making requests to /api/ routes in VueJS Progressive Web Apps (PWA

I recently developed a Vuejs project with PWA capabilities, but encountered an issue when building its production version. The project seems to be using cached versions of API requests instead of making fresh network calls. I am trying to find a way to eit ...

Is it possible for $watch to monitor the props in Vue.js?

Is it possible to listen for changes in props in Vue.js? I experimented in my testing environment, and discovered that I am unable to watch the props: In my index.vue file: <test-com :data="pass_data"></test-com> ... export default { d ...

The variable "theSport" is not recognized as a property or method in Vue.js instance

Currently, I am tackling a basic form in VueJs but I'm struggling to pinpoint why my code is throwing an error message. "[Vue warn]: Property or method "theSport" is not defined on the instance but referenced during render" Despite searching extensi ...

A guide to accessing OS environment variables using Vue 2.7

Setting environment variables in my OS has been straightforward: However, I am facing an issue when trying to access these variables in my Vue app. Here is my .env file content: VUE_APP_GATEWAY_ADDRESS=localhost:8083 VUE_APP_GATEWAY_ADDRESS_TEST_TWO=gwat ...

Creating Vue3 Component Instances Dynamically with a Button Click

Working with Vue2 was a breeze: <template> <button :class="type"><slot /></button> </template> <script> export default { name: 'Button', props: [ 'type' ], } </scr ...

Find the position of the object in a list

I have an array that looks something like this data: Array(3) 0: data: Object account_id: (...) address_1: (...) address_2: (...) amount: 10.00 id: 1234 ... 1: data: Object account_id: (...) address_ ...

What are the steps to implement $navigateTo() in a NativeScript Vue application?

What could be causing $navigateTo(Page) to not work? Visit this link for more information ...

Is it necessary to include async/await in a method if there is already an await keyword where it is invoked?

Here are the two methods I have written in Typescript: async getCertURL(pol: string): Promise<string> { return await Api.getData(this.apiUrl + pol + this.certEndpoint, {timeout: 60000}).then( (response) => { return response.data.certUR ...

Continue looping in Javascript until an empty array is identified

Currently, I am in search of a solution to create a loop in Javascript that continues until the array of objects is empty. The object I am working with looks like this: "chain": { "evolves_to": [{ "evolves_to": [{ ...

Troubleshooting the issue of React forms hook not functioning properly with Material UI Select input

How the Textfield below should load: How it actually loads: My Select component, created using Material UI and React form hook, is not loading the default value as expected. The component should start with a pre-selected value, which is provided in the c ...

TypeScript encountered an error with code TS2554, indicating that it was expecting 0 arguments but instead received 1 in an Ionic application

Hello everyone! I'm encountering an issue in my project involving a Type Script error TS2554: Expected 0 arguments, but got 1. This error is preventing me from being able to select other options for custom input pop up. In this forum post, I have shar ...

Vue.js is displaying an error message stating that the data property is

I am struggling to access my data property within my Vue.js component. It seems like I might be overlooking something obvious. Below is a condensed version of my code. The file StoreFilter.vue serves as a wrapper for the library matfish2/vue-tables-2. &l ...

Delivering static HTML routes in a React App using Typescript

I am working on a React app with functional components, and everything is working perfectly with its own CSS. Now, I have a separate static HTML file (FAQ) with its own CSS and design that I want to incorporate as a new route at /FAQ. I don't want th ...