nativescript-google-maps-sdk icon indicating copy to clipboard operation
nativescript-google-maps-sdk copied to clipboard

Custom infoWindowTemplate with Angular2

Open dimitriospafos opened this issue 7 years ago • 23 comments

I'm trying to use the infoWindowTemplate with Angular2, but I can't see any example or documentation for it. My question is how can I define a template for a custom marker's window using Angular2 and nativescript?

Any help would be appreciated.

dimitriospafos avatar Nov 09 '17 01:11 dimitriospafos

It would be beneficial for this SDK to have example of custom ifoWindowTemplate implementatation for Angular under ng-demo. Thanks a lot.

ochemerys avatar Nov 09 '17 03:11 ochemerys

Is there anyone that can provide an example on how to implement the custom info windows for Angular2? It seems there was a pull request to fix some issues with the Angular implementation so I assume it is already possible but we just need an example. https://github.com/dapriett/nativescript-google-maps-sdk/pull/183

kilka avatar Nov 14 '17 20:11 kilka

how can i use infoWindowTemplate in native script with angular 2 . Did anyone successfully implement infoWindowTemplate with angular 2?

harsh-raval avatar Nov 23 '17 20:11 harsh-raval

Here is work around for Angular without example, it seems there is no way to directly set templates in Angular template (.html), for our purpose we directly created template in component code (.ts) and assigned it to MapView

const templates = <template key="dropTemplate"> <StackLayout orientation="horizontal" verticalAlignment="center" margin="0 0 0 0" width="150" height="30" > <StackLayout backgroundColor="black" verticalAlignment="center" width="50" height="30"> <Label text="${result.duration}" textAlignment="center" textWrap="true" style="color:white;font-size:12;"></Label> </StackLayout> <Label text="${result.drop.address}" verticalAlignment="center" paddingLeft="10" style="color:black;font-size:15;"></Label> </StackLayout> </template> <template key="pickupTemplate"> <StackLayout orientation="horizontal" verticalAlignment="center" margin="0 0 0 0" width="150" height="30" > <StackLayout backgroundColor="black" verticalAlignment="center" width="50" height="30"> <Label text="${result.duration}" textAlignment="center" textWrap="true" style="color:white;font-size:12;"></Label> </StackLayout> <Label text="My Current Location" verticalAlignment="center" paddingLeft="10" style="color:black;font-size:15;"></Label> </StackLayout> </template>; this.mapView.infoWindowTemplates = templates

and then added following line while creating marker marker.infoWindowTemplate = 'pickupTemplate';

Works like charm.

when you are building app using web pack you need to add following code to main.aot.ts otherwise it will not work , reason is that what we have written above is XML template and somehow during build process with webpack it does not find list-view module, below code is copied from NativeScript JavaScript template if (global.TNS_WEBPACK) { //registers tns-core-modules UI framework modules require("bundle-entry-points"); }

it would be interesting to see how this can be achieved using Angular template like shown in Demo App with XML.

one more missing puzzle is how to keep multiple info window open, it appears that you can only open one marker window at time. trick could be to build custom icon with information embedded, see following stack flow discussion on that

https://stackoverflow.com/questions/32984118/show-info-window-on-every-marker-at-a-time

milansar avatar Nov 30 '17 09:11 milansar

There is no property infoWindowTemplates exposed on the MapView class. How do you assign the template to it?

dimitriospafos avatar Dec 01 '17 02:12 dimitriospafos

sorry for late reply

Actually MapView has infoWindowTemplates property, but it is not defined in typescript definition file (map-view.d.ts). Due to that typescript complains about it.

You have two options for it, Option 1 (Recommended) as type for your local variable , do following public mapView: MapView & {infoWindowTemplates: string }; This will make typescript accept infoWindowTemplates property and will not complain about it Option2 (Not Recommended) add in your node-modules infoWindowTemplates property into map-view.d.ts,

milansar avatar Dec 11 '17 13:12 milansar

@milansar Thanks a lot. Works like charm!!!

dimitriospafos avatar Dec 14 '17 02:12 dimitriospafos

@dimitriospafos Glad it worked :-)

milansar avatar Dec 14 '17 07:12 milansar

@milansar Your solution works great! Is it possible to detect tap events on different elements inside the custom info window?

racknoris avatar Dec 19 '17 00:12 racknoris

@racknoris , I tried but could not make it work. you can listen to click event on infoWindow but not elements inside.

milansar avatar Dec 24 '17 13:12 milansar

@milansar is there way to put custom angular component inside infoWindowTemplate? I have tried but i am getting error:

System.err: com.tns.NativeScriptException:
System.err: Calling js method getInfoContents failed
System.err:
System.err: Error: Parsing XML at 3:7
System.err:  > Module 'ui/offer-details' not found for element 'OfferDetails'.
System.err:    > com.tns.NativeScriptException: Failed to find module: "ui/offer-details", relative to: app/tns_modules/
System.err:       com.tns.Module.resolvePathHelper(Module.java:146)
System.err:     com.tns.Module.resolvePath(Module.java:55)
System.err:     com.tns.Runtime.callJSMethodNative(Native Method)
System.err:     com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1088)
System.err:     com.tns.Runtime.callJSMethodImpl(Runtime.java:970)
System.err:     com.tns.Runtime.callJSMethod(Runtime.java:957)
System.err:     com.tns.Runtime.callJSMethod(Runtime.java:941)
System.err:     com.tns.Runtime.callJSMethod(Runtime.java:933)
System.err:     com.tns.gen.com.google.android.gms.maps.GoogleMap_InfoWindowAdapter.getInfoContents(GoogleMap_InfoWindowAdapter.java:17)
System.err:     com.google.android.gms.maps.zzg.zzi(Unknown Source)
System.err:     com.google.android.gms.maps.internal.zzi.onTransact(Unknown Source)....
...

bori87 avatar Jan 08 '18 00:01 bori87

@bori87 , I have not tried it. I think problem is that InfoWindowTemplate content is parsed as Vanila NativeScript XML, not as Angular XML thus it is not able to find custom Angular Component you created.

I am not expert of Vanila NativeScript but it appears to me that you need to register your Angular component somewhere to make it available to Vanila NativeScript XML

milansar avatar Jan 08 '18 05:01 milansar

@milansar , Is there a way to dynamically replace some of the content of the infoWindowTemplate? (angular) I have a template like this :

<template key="example"> 
     <GridLayout rows="*" width="100" height="70"> 
         <StackLayout row="0" orientation="horizontal">                                   
           <Label text="${PLACEHOLDER}">
           </Label>
         </StackLayout>
      </GridLayout>
</template>;


I want to be able to replace the PLACEHOLDER each time I create a new marker. I tried replacing the PLACEHOLDER on the mapView.infoWindowTemplates before creating each marker but seems like it only keeps the last replaced template for all of them when they are rendered on the map.

The option of having multiple templates for each case is not viable since the value for the placeholder will be loaded dynamically from an api.

Any help would be appreciated.
Thanks

dimitriospafos avatar Jan 13 '18 01:01 dimitriospafos

@dimitriospafos and @bori87

I figured there is way to have data binding on custom template. At time of creating info window, marker is used as binding context, It means property we set on marker is bound to template at rendering time. thus we can use userData property to provide custom data to template

your code need to be changed as following

<template key="example"> <GridLayout rows="*" width="100" height="70"> <StackLayout row="0" orientation="horizontal"> <Label text="{{userData.placeholder}}"> </Label> </StackLayout> </GridLayout> </template>;

Then while creating marker

let marker = new Marker(); let icon = new Image(); icon.src = '~/assets/markers/round.png'; icon.imageSource = imageSource.fromFile('~/assets/markers/round.png'); marker.icon = icon; marker.position = Position.positionFromLatLng(latitude, longitude); marker.userData = {placeholder: "hello world"}; marker.infoWindowTemplate = "example";

I hope this help

milansar avatar Jan 13 '18 06:01 milansar

@milansar

Thank you for all the help. It works!!! I really appreciate you putting the time into it to help.

dimitriospafos avatar Jan 13 '18 20:01 dimitriospafos

While we have a "workaround", it would be really nice if the maintainer would just expose the capability through the MapView TS integraion

westlakem avatar Jan 28 '18 18:01 westlakem

Send over a pull request @westlakem - I'll be glad to take a look when I get a chance.

dapriett avatar Jan 28 '18 19:01 dapriett

I would but I got to warn you, it won't be immediate... this is a weekend project for me and I'm new to the ecosystem. Not trying to make excuses, just sayin it would take a while for me to get around to it

westlakem avatar Jan 28 '18 23:01 westlakem

I hear ya @westlakem. I'm not doing any mobile development on my current projects, so you'll be waiting even longer for me. But I try to make time for pull requests when I can.

dapriett avatar Jan 29 '18 15:01 dapriett

Idk how you people managed to get it working because as soon as I add a <template> tag I get this:

Module 'ui/template' not found for element 'Template'.

Can someone explain how to solve this?

chrillewoodz avatar Nov 05 '18 13:11 chrillewoodz

What is correct way to put button tap action on the info window? Because the element disappear when i put (tap) action

elgibor-solution avatar Jan 28 '19 15:01 elgibor-solution

@dimitriospafos and @bori87

I figured there is way to have data binding on custom template. At time of creating info window, marker is used as binding context, It means property we set on marker is bound to template at rendering time. thus we can use userData property to provide custom data to template

your code need to be changed as following

<template key="example"> <GridLayout rows="*" width="100" height="70"> <StackLayout row="0" orientation="horizontal"> <Label text="{{userData.placeholder}}"> </Label> </StackLayout> </GridLayout> </template>;

Then while creating marker

let marker = new Marker(); let icon = new Image(); icon.src = '~/assets/markers/round.png'; icon.imageSource = imageSource.fromFile('~/assets/markers/round.png'); marker.icon = icon; marker.position = Position.positionFromLatLng(latitude, longitude); marker.userData = {placeholder: "hello world"}; marker.infoWindowTemplate = "example";

I hope this help

Do you know if it is possible in Angular? I tried using something like <Label [text]="userData.title" but it didn't work ... Thanks Marco

mrzanirato avatar Aug 20 '20 11:08 mrzanirato

@dimitriospafos and @bori87 I figured there is way to have data binding on custom template. At time of creating info window, marker is used as binding context, It means property we set on marker is bound to template at rendering time. thus we can use userData property to provide custom data to template your code need to be changed as following <template key="example"> <GridLayout rows="*" width="100" height="70"> <StackLayout row="0" orientation="horizontal"> <Label text="{{userData.placeholder}}"> </Label> </StackLayout> </GridLayout> </template>; Then while creating marker let marker = new Marker(); let icon = new Image(); icon.src = '~/assets/markers/round.png'; icon.imageSource = imageSource.fromFile('~/assets/markers/round.png'); marker.icon = icon; marker.position = Position.positionFromLatLng(latitude, longitude); marker.userData = {placeholder: "hello world"}; marker.infoWindowTemplate = "example"; I hope this help

Do you know if it is possible in Angular? I tried using something like <Label [text]="userData.title" but it didn't work ... Thanks Marco

Hey @mrzanirato did you set the userData for the specific marker

var marker = new Marker();
marker.position = Position.positionFromLatLng(this.latitude, this.longitude);
marker.userData = { title : "This is title" };
mapView.add(marker);

subhojit-me avatar Mar 22 '21 12:03 subhojit-me