bluehalo / ngx-leaflet-tutorial-plugins

MIT License
22 stars 10 forks source link

How to write a plugin in typescript #4

Closed AndreasSchmid1 closed 6 years ago

AndreasSchmid1 commented 6 years ago

Thanks for this tutorial section @asymmetrik , it helped me a lot.

I integrated the following custom lib https://github.com/whitequark/Leaflet.Nanoscale

Things I did:

  1. I added the Control.Nanoscale.js to assets/js/Control.Nanoscale.js

  2. I added "import * as L from 'leaflet'" to Control.Nanoscale.js because otherwise you will receive an (error "ReferenceError: L is not defined")

  3. I added "scripts": [ "../src/assets/js/Leaflet.Nanoscale.js" ],

  4. Added typings

    import * as L from 'leaflet'; declare module 'leaflet' { var nanoscale: any; }

  5. Added the nanoscale control

import "../../../assets/js/Control.Nanoscale.js";

L.control.nanoscale({ nanometersPerPixel: 1000, }).addTo(this.map);

But the code of Control.Nanoscale.js is so short I would prefer to write the code in typescript myself.

Is it technically possible to write leaflet plugins in Angular / typescript?

Thank you for help in advance

reblace commented 6 years ago

You can. It depends on the complexity of the control and what you're trying to do specifically. But, you could use the (leafletMapReady) output binding to get a handle to the map and then you can do whatever you want to (add a custom control, add event handlers, etc.).

If you want to wrap it into a custom component or directive that works with ngx-leaflet, you can use https://github.com/Asymmetrik/ngx-leaflet-draw or https://github.com/Asymmetrik/ngx-leaflet-markercluster as examples of how to inject the LeafletDirective into your custom component/directive. That allows you direct access to the map and other functionality within ngx-leaflet.

Check the ngx-leaflet README for details about making sure change detection works on changes in event handlers.

AndreasSchmid1 commented 6 years ago

Thank you very much @reblace I will try that

AndreasSchmid1 commented 6 years ago

I'm trying to write my first native typescript (without js dependencies) leaflet plugin and I am struggling a little bit. What I tried (I started with a service before trying a directive):

  1. I tried to create a typescript implementation of this plugin https://github.com/azavea/Leaflet.zoomdisplay/blob/master/src/L.Control.ZoomDisplay.js
/*
 * L.Control.ZoomDisplay shows the current map zoom level
 */
import { Injectable } from '@angular/core';
import * as L from 'leaflet';

@Injectable()
export class LeafletControlPower {

     zoomDisplay = L.Control.extend({
        options: {
            position: 'topleft'
        },

        onAdd: function (map) {
            this._map = map;
            this._container = L.DomUtil.create('div', 'leaflet-control-zoom-display leaflet-bar-part leaflet-bar');
            this.updateMapZoom(map.getZoom());
            map.on('zoomend', this.onMapZoomEnd, this);
            return this._container;
        },

        onRemove: function (map) {
            map.off('zoomend', this.onMapZoomEnd, this);
        },

        onMapZoomEnd: function (e) {
            this.updateMapZoom(this._map.getZoom());
        },

        updateMapZoom: function (zoom) {
            if(typeof(zoom) === "undefined"){zoom = ""}
            this._container.innerHTML = zoom;
        }
    });

    mergeOptions = L.Map.mergeOptions({
        zoomDisplayControl: true
    });

    addInitHook = L.Map.addInitHook(function () {
        if (this.options.zoomDisplayControl) {
            this.zoomDisplayControl = new this.zoomDisplay();
            this.addControl(this.zoomDisplayControl);
        }
    });

    constructor() { 

    }

    public ZoomDisplay(options: any)
    {
        return new this.zoomDisplay(options);

    }

}
  1. Add it to the map

this.powerControl.ZoomDisplay({}).addTo(this.map);

An error comes up: TypeError: this.zoomDisplay is not a constructor

I am pretty sure that I did a lot wrong here because i don't understand how to transform the js concept of this class into the directive/service concept of angular. I am also wondering if my the idea (writing native typescript plugins) makes sense. The idea came to me only because I can debug with VS code.