rowanwins / leaflet-easyPrint

A leaflet plugin which adds an icon to print the map - Demo @ http://rowanwins.github.io/leaflet-easyPrint/
MIT License
248 stars 137 forks source link

Use leaflet-easyPrint in Typescript app #94

Open ialixandroae opened 5 years ago

ialixandroae commented 5 years ago

I tried to import the plugin into a Typescript app and also added the code into the typings file to extend L.control from leaflet but gotUncaught TypeError: L.control.easyPrint is not a function error.

This is the code from typings file:

import 'leaflet';

declare module 'leaflet' {

    namespace Map {
        export interface MapOptions {

            easyPrintControl? : boolean;
        }
    }

    export interface ControlStatic {

        EasyPrint: Control.EasyPrintStatic;
    }

    namespace Control {

        export interface EasyPrintStatic {
            new (options?: IEasyPrintConstructorOptions): EasyPrint;

        }

        export interface IEasyPrintConstructorOptions {
            title: string;
            position: string;

        }

        export interface EasyPrint extends L.Control {

        }

    }

    export namespace control {
            export function easyPrint (options?: Control.IEasyPrintConstructorOptions): Control.EasyPrint;
    }
}

For some reason, my IDE interpretor accepts easyPrint function on L.control but my browser throws the error...

Not really sure where to go from here to be able to use the plugin

rowanwins commented 5 years ago

Hmmm I dont know much about typescript sorry @ialixandroae :(

ialixandroae commented 5 years ago

@rowanwins thanks for your reply! Oh, I'm sorry to hear that :(

I'll try to have this done; also maybe somebody else interested could help

martinhouryfors commented 5 years ago

Hi, I think you can use easyPrint like this : First install easyPrint with npm npm install leaflet-easyprint --save

Then, use it in your typescript file.

import * as Leaflet from 'leaflet';
import 'leaflet-easyprint';
...
map : Leaflet.Map;
...
drawMap() {
        //initialize the map
        this.map = Leaflet.map('map',
            {
                center: [...],
                zoomDelta: 1,
                zoom: 14
            });       
        (Leaflet as any).easyPrint({
            title: 'My awesome print button',
            position: 'bottomleft',
            sizeModes: ['A4Portrait', 'A4Landscape']
        }).addTo(this.map);
}
...

@ialixandroae

And you should see the easyPrint control the the map

rowanwins commented 5 years ago

Thanks for sharing @martinhouryfors

ialixandroae commented 5 years ago

@martinhouryfors thanks for your message and feedback! Unfortunately I get the same error L.easyPrint is not a function

I imported leaflet-easyprint in my main .ts file (where the map object is created) using import 'leaflet-easyprint';

After the map object is created, I used :

(L as any).easyPrint({
            title: 'My awesome print button',
            position: 'bottomleft',
            sizeModes: ['A4Portrait', 'A4Landscape']
}).addTo(map); 

Maybe the code is ok but something in the typings file is wrong...

jlaverdure-talis commented 4 years ago

Hello ialixandroae,

Did you find a solution for this problem?

ialixandroae commented 4 years ago

Hi @jlaverdure-talis ,

Unfortunatelly no and I haven't tried since. At the moment I'm not sure if this is something in the core of the library or something with my Typescript configuration (something wrong or missing?)

sushiljain1989 commented 4 years ago

I'm also facing the same issue. Trying to use it in a React web app. Did anyone manage to find the solution?

rcollette commented 4 years ago

You will want to create a declaration module leaflet-easyprint.d.ts and use the module augmentation functionality of Typescript.

import { Control } from 'leaflet';

export class EasyPrintControl extends Control {
  // control specific methods and properties here
}

export interface EasyPrintOptions {
    hidden: boolean;
    exportOnly: boolean;
    // ...
}

declare module 'leaflet' {
  export function easyPrint(options: EasyPrintOptions): EasyPrintControl;
}

Then where used you import

import * as L from 'leaflet';
import { Map } from 'leaflet';
import 'leaflet-easyprint';
import { EasyPrintControl, EasyPrintOptions } from 'pathTo/leaflet-easyprint'; //the declaration file.

I really wish a new major release of leaflet would come along the is either written in TS or at least more closely aligns with Ecmascript classes. Seeing every object as type "NewClass" makes type checking difficult at runtime. The augumentation method of creating classes essentially ignores encapsulation principles.

Anyway, hope that helps.

ialixandroae commented 4 years ago

Hi @rcollette , Thanks for your feedback and message! I've tried your proposal and I don't have any problems at compilation time but at runtime.

I am getting Uncaught TypeError: L.easyPrint is not a function in the browser console.

This comes when I run:

L.easyPrint({
            title: 'Test',
            position: 'bottomright',
            sizeModes: ['A4Portrait', 'A4Landscape']
        }).addTo(map);
rcollette commented 4 years ago

Just double checking, do you have the leaflet imports before the easyprint imports. Sometimes an ide will reorder the imports.

I can't wait till we move away from global imports like this.

yog3sha commented 3 years ago

Hello @rcollette , can you please share how you used those controls after creating declaration file and importing from it? I am using this library inside a Vue + TS project and I cannot figure out how to actually trigger printing map on a function call.

rcollette commented 3 years ago

@yog3sha - I forget the reason but we had some issue with easyprint and had to remove it from the project. We wound up posting the current map image to to the server to generate PDFs server side.

john-chase-noaa commented 3 years ago

@rcollette - Could you elaborate on how you achieved this? It is almost exactly our requirement. Actually need the the file to be downloaded to the server. Looking at WGET or CURL, but I need this to be automatic and not button fired.

rcollette commented 3 years ago

@john-chase-noaa I can post the methodology, but not specific code.

Use domToImage to convert the mapPane to a dataUrl Make an API call to a Node server that includes the dataUrl Use PdfKit.PdfDocument.image() to render the data url in the pdf document.

You will likely not get a 100% accurate rendering of all layers that are on the screen because not everything is in the mapPane. I want to say that the attributions and controls aren't part of the generated image. So we passed the attributions to the server as well and rendered them elsewhere in our PDF Document.

john-chase-noaa commented 3 years ago

@rcollette - Thanks much, that's great info, code not necessary...

GhadaAjimiDblog commented 2 years ago

Je ne sais pas s'ils ont corrigé le bug mais (L as any).easyPrint fonctionne pour moi mais il ne peut pas inmprimer les icones. Qlq sais pourquoi?