Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to subscribe to click event on Cluster Marker - agm-marker-cluster #1272

Closed
Soberwolfpack opened this issue Dec 25, 2017 · 3 comments
Closed
Labels

Comments

@Soberwolfpack
Copy link

I am developing Angular 4 bases application where in I need to integrate google maps and have a functionality of displaying clusters. If there are multiple locations at same lat-long, a cluster is shown with the number of locations.Further, I need to display a popup dialog on clicking this cluster. I am able to get the clustering working using agm-marker-cluster, but I am not sure the event to subscribe to, when the user clicks on the cluster. Can someone let me know how to go about it.

Thanks.

@Martin-B
Copy link

I hope this helps, this is what I ended up doing. The click events are in the clustering directive that calls the service. The markerClicked function in the .ts responds to click events. The template has conditional tags that allow visible/hidden behaviour for the marker metadata to show.

// File marker-cluster.directive.ts
// *******************************

import { Directive, OnInit, Input, EventEmitter } from '@angular/core';
import { GoogleMapsAPIWrapper } from '@agm/core';
import { GoogleMap, Marker } from '@agm/core/services/google-maps-types';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { AppService } from '../service/app.service';
import 'js-marker-clusterer/src/markerclusterer.js';

declare const google;
declare const MarkerClusterer;

@Directive({
  selector: 'marker-cluster',
  outputs: ['markerClick'],
})


export class MarkerCluster implements OnInit {

  markerClick: EventEmitter<string> = new EventEmitter<string>();

  public environment = environment;
  //set google maps defaults
    //zoom level
    zoom: number = 12;
    //start position
    lat:number  = 45.508755;
    lng:number = -73.587579;

    urlMarkers = environment.urlServiceWeb + 'liste/pub/all/all/true/false';

    markers: marker[] = [];
    map: any;
    selectedMarker: any;

  constructor(
    private gmapsApi: GoogleMapsAPIWrapper,
    private httpService: AppService,

    ) { }

ngOnInit() {
    this.gmapsApi.getNativeMap().then(map => {
      this.map = map;
      this.httpService.getData(this.urlMarkers)
      .subscribe(
         data => {

            const corveeMarkers = [];

            for (let key in data.markers) {
              let statusCorvee = data.markers[key].estPublic;
              let iconUrl;
              if(statusCorvee==true){
                 iconUrl = {
                  url: 'assets/icons/icon-public.png'
                }
              }else{
                iconUrl = {
                  url: 'assets/icons/icon-prive.png'
                }
              }

              var marker = new google.maps.Marker({
                position: new google.maps.LatLng(data.markers[key].latitude, data.markers[key].longitude),
                icon: iconUrl
              });
              google.maps.event.addListener(marker, 'click', () => {

                  this.markerClick.emit(data.markers[key]);
                  this.selectedMarker = data.markers[key];

              });
               corveeMarkers.push(marker);
            }
            var markerCluster = new MarkerClusterer(this.map, corveeMarkers, {imagePath: "https://raw.githubusercontent.com/googlemaps/js-marker-clusterer/gh-pages/images/m"});
        },
        error => {
            //console.log(error);
        }
       );
    });
  } // end ngOnInit
}

interface marker {
  lat: number;
  lng: number;
  status: string;
}

// *******************************

// File my-module.ts
// *******************************

import { Component, OnInit, NgZone} from '@angular/core';
import { Response, HttpModule } from '@angular/http';
import { HttpClientModule } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AgmCoreModule, MapsAPILoader} from '@agm/core';
import { GoogleMap, Marker } from '@agm/core/services/google-maps-types';
import { AppService } from '../service/app.service';
import { AlertService } from '../service/app.alert.service';
import { environment } from '../../environments/environment';
import { FormControl, FormGroup,  FormBuilder } from '@angular/forms';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import 'rxjs/Rx';
import {IMyOptions} from 'mydatepicker';
import { MarkerCluster } from './marker-cluster.directive';
import { Title } from "@angular/platform-browser";

declare const google;
declare const MarkerClusterer;


@Component({
  selector: 'app-corvee-form',
  templateUrl: './participer.component.html',
  styleUrls: ['./participer.component.less'],
  // providers: [ AppService, AlertService , {
  //     provide: MapsAPILoader, useClass: NoOpMapsAPILoader
  //   }],
  providers: [ AppService, AlertService],

})

export class ParticiperComponent implements OnInit {

  public environment = environment;
  public isRegistrationActive = environment.isRegistrationActive; // Toggle this value in environment files in order to enable and disable registration
	map: any;
	googleMarkers: any;
	//set google maps defaults
    //zoom level
   	zoom: number = 12;
    //start position
    lat:number  = 45.508755;
    lng:number = -73.587579;
    corvees: string;

    urlMarkers = environment.urlServiceWeb + 'liste/pub/all/all/true/false';
    urlCorveesAvenir = environment.urlServiceWeb + 'liste/stats/all/all/false';

    markers: marker[] = [];
    totalCorveePublic: number;
    publiCorvee: marker[] = [];
    selectedMarker: any;
    infoMarkerDisplay: boolean;
    filterPubliCorvee: any[];
    searchField: FormControl;
    searchForm: FormGroup;
    searchDateField: any;
    messageText: string;
    corveesAvenir: number = 0;


    private isSortASC: boolean;
    private sortElement:string;


    private myDatePickerOptions: IMyOptions = {
        selectionTxtFontSize: '14px',
        minYear: 2017,
        maxYear: 2018,
        openSelectorOnInputClick: true,
        dayLabels: {su: "Dim", mo: "Lun", tu: "Mar", we: "Mer", th: "Jeu", fr: "Ven", sa: "Sam"},
        monthLabels: {1: "Jan", 2: "Fév", 3: "Mar", 4: "Avr", 5: "Mai", 6: "Juin", 7: "Juil", 8: "Aoû", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Déc"},
        dateFormat: "dd/mm/yyyy",
        todayBtnTxt: "Aujourd'hui",
        firstDayOfWeek: "mo",
        sunHighlight: true,
        editableDateField: false
    };

    public arrondissement = [
	    'Ahuntsic-Cartierville',
	    'Anjou',
	    'Côte-des-Neiges–Notre-Dame-de-Grâce',
	    'Lachine',
	    'LaSalle',
	    'Le Plateau-Mont-Royal',
	    'Le Sud-Ouest',
	    'L’Île-Bizard–Sainte-Geneviève',
	    'Mercier–Hochelaga-Maisonneuve',
	    'Montréal-Nord',
	    'Outremont',
	    'Pierrefonds-Roxboro',
	    'Rivière-des-Prairies–Pointe-aux-Trembles',
	    'Rosemont–La Petite-Patrie',
	    'Saint-Laurent',
	    'Saint-Léonard',
	    'Verdun',
	    'Ville-Marie',
	    'Villeray–Saint-Michel–Parc-Extension'
	    ];


	constructor(
      private titleService: Title,
      private httpService: AppService,
      private alertService: AlertService,
      private mapsAPILoader: MapsAPILoader,
      private ngZone: NgZone,
      private fb:FormBuilder,
      private route: ActivatedRoute,
      private router: Router

   ) {}


  ngOnInit() {

  this.httpService.getData(this.urlCorveesAvenir)
  .subscribe(
    data => {
      if(data.markers.length > 0){
        this.corveesAvenir = data.markers.length;
      }   
    });

	this.httpService.getData(this.urlMarkers)
		.subscribe(
	  	data => {
        if('error' in data) {
          this.router.navigate(['./message'], { queryParams: { confirmation: data.error } }); return;
        }

	  	 	const corveeMarkers = [];

	  	 	for (let key in data.markers) {
	  	 	 	let keyArrond = data.markers[key].arrondissement;

          if(data.markers[key].siPluieAnnulation == 'A_LIEU'){
            data.markers[key].siPluieAnnulation = 'La corvée a lieu';
          }else if(data.markers[key].siPluieAnnulation == 'ANNULE'){
            data.markers[key].siPluieAnnulation = 'La corvée est annulée';
          }else if(data.markers[key].siPluieAnnulation == 'REPORTE'){
            data.markers[key].siPluieAnnulation = 'La corvée est reportée';
          }

	  	 	 	corveeMarkers.push({
	  	 	 		lat: parseFloat(data.markers[key].latitude),
	  	 	 		lng: parseFloat(data.markers[key].longitude),
	  	 	 		nom: data.markers[key].nom,
	  	 	 		id: data.markers[key].id,
	  	 	 		organisateur: data.markers[key].organisateur,
	  	 	 		status: data.markers[key].estPublic,
	  	 	 		arrondissement: this.arrondissement[keyArrond-1],
	  	 	 		dateDebut: data.markers[key].dateDebut,
	  	 	 		dateFin: data.markers[key].dateFin,
            description: data.markers[key].description,
            siPluieAnnulation: data.markers[key].siPluieAnnulation,
            dateReport: data.markers[key].dateReport,
            nbParticipantsRestants: data.markers[key].nbParticipantsRestants
	  	 	 	});
	  	 	}

	  	 	this.markers = corveeMarkers;

	  	  this.publiCorvee = corveeMarkers.filter(markers => markers.status === true);
	  	  this.filterPubliCorvee = this.publiCorvee;

        this.publiCorvee = this.publiCorvee.sort(function(a,b){
          
          let corveeDateA = new Date(a.dateDebut);
          let corveeDateB = new Date(b.dateDebut);
         
          return corveeDateA.getTime() - corveeDateB.getTime();
        });

	  	},
	  	error => {
	       this.router.navigate(['./message'], { queryParams: { confirmation: 'DEFAULT' } });
			}
		 );

		this.searchForm = this.fb.group({
		 	searchName: new FormControl(),
		 	searchDate: new FormControl(),
		 	searchArrondissement: 'all',
		 });

	} //end ngOnInit

	markerClicked(marker: marker) {
    //remplacer avec le nom du arrondissement
    let keyArrond = parseFloat(marker.arrondissement);
    marker.arrondissement = this.arrondissement[keyArrond-1];

    this.infoMarkerDisplay = true;
    this.selectedMarker = marker;

    if( marker.siPluieAnnulation == 'A_LIEU'){
      marker.siPluieAnnulation = 'La corvée a lieu';
    }else if( marker.siPluieAnnulation == 'ANNULE'){
      marker.siPluieAnnulation = 'La corvée est annulée';
    }else if( marker.siPluieAnnulation == 'REPORTE'){
      marker.siPluieAnnulation = 'La corvée est reportée';
    }
	}

	hideInfoMarker($event: MouseEvent){
		this.infoMarkerDisplay = false;
	}

}

interface marker {
  lat: number;
  lng: number;
  dateDebut: 'fullDate';
  dateFin: 'fullDate';
  dateReport: 'fullDate';
  nom?: string;
  draggable: boolean;
  url: string;
  id: string;
  organisateur: string;
  status: string;
  arrondissement: string;
  description: string;
  siPluieAnnulation: string;
  nbParticipantsRestants: number;
}

// *******************************

// My-module.html template

// Custom info window

<div  id="infowindow" *ngIf="infoMarkerDisplay">
  <div *ngIf="selectedMarker">
    <div *ngIf="selectedMarker.nbParticipantsRestants == 0" class="message-inscription">
     
        // info window content 
       
    </div>
  </div>
</div>

// agm-map obtains marker data from the cluster directive, click event responds to function
markerClicked in my-module.ts


<div id="publicmap">
   <agm-map
         [latitude]="lat"
         [longitude]="lng"
         [zoom]="zoom"
         [disableDefaultUI]= false
         >
     <marker-cluster (markerClick)='markerClicked($event)'>
     </marker-cluster>
   </agm-map>
 </div>

@stale
Copy link

stale bot commented Nov 13, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 13, 2018
@stale stale bot closed this as completed Nov 20, 2018
@ruisilva450
Copy link

ruisilva450 commented Apr 30, 2019

@Martin-B Can you provide a more complete example of this?
A repo perhaps?

ghost pushed a commit that referenced this issue Sep 17, 2019
Add clusterClick event to MarkerCluster.

fixes: #1272
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants