Building Maps in Angular using Leaflet, Part 3: The Popup Service

Chris Engelsma

In my last post, we expanded upon our Angular Leaflet project by creating a service to serve up Markers. We’re going to now do the same thing for popups.

Our map is now populated with markers, and we’re going to set up our map so that the user will be presented with a pop-up containing information about a selected marker.

Setup

By now, our directory structure should look like this:

leaflet-example
|_ node_modules/
|_ package.json
\_ src/
    \_ app/
        |_ app.module.ts
        |_ app.routing.ts
        |_ app.component.ts
        |_ app.component.html
        |_ app.component.scss
        |
        |_ map/
        |     |_ map.component.ts
        |     |_ map.component.html
        |     \_ map.component.scss
        |
        \_ _services/
              |_ marker.service.ts

Just as we did with the marker service, navigate to the _services/ directory and use the Angular CLI’s generate command to create our pop-up service:

$ ng generate service pop-up

Add this new service as a provider in your app.module.ts.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { MapComponent } from './map/map.component';
import { MarkerService } from './_services/marker.service';
import { PopUpService } from './_services/pop-up.service';

@NgModule({
  declarations: [
    AppComponent,
    MapComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    MarkerService,
    PopUpService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

🐊 Alligator.io recommends

Our recommended Angular courses

Designing Our Pop-ups

Crack open your new PopUpService and create an empty function responsible for creating a pop-up:

pop-up.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PopUpService {

  constructor() { }

  makeCapitalPopup(data: any): string {

  }
}

This function will be responsible for taking our marker data and creating a beautifully formatted pop-up.

We’re only concerned with what goes inside the pop-up, as Leaflet will handle the actual pop-up itself.

Our data are very simple so we’re going to keep this basic:

pop-up.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PopUpService {

  constructor() { }

  makeCapitalPopup(data: any): string {
    return `` +
      `<div>Capital: ${ data.name }</div>` +
      `<div>State: ${ data.state }</div> +
      `<div>Population: ${ data.population }</div>`
  }
}

Let’s inject this PopUpService within the MarkerService:

marker.service.ts

constructor(private http: HttpClient,
        private popupService: PopUpService) { }

Huh? A service injected into a service?

Yes! This is a perfectly OK thing to do. By adding our services to our providers stanza within app.modules.ts we are creating the services as singleton providers to the entire application, so Angular won’t complain about dependency.

Back to our recently-injected MarkerService: before we add each circle to the map, we’ll need to bind them to their respective pop-ups.

marker.service.ts

makeCapitalCircleMarkers(map: L.map): void {
    this.http.get(this.capitals).subscribe((res: any) => {

      // Find the maximum population to scale the radii by.
      const maxVal = Math.max(...res.features.map(x => x.properties.population), 0);

      for (const c of res.features) {
        const lat = c.geometry.coordinates[0];
        const lon = c.geometry.coordinates[1];
        const circle = L.circleMarker([lon, lat], {
          radius: MarkerService.ScaledRadius(c.properties.population, maxVal)
        }); //.addTo(map); <-- removed this

        circle.bindPopup(this.popupService.makeCapitalPopup(c));

        circle.addTo(map);
      }
    });
  }

Build and run your application and click one of your markers.

Coming at you with some capital city facts

Fantastic! ✨

In the next post, we’ll learn how to plot the state shapes and generate a nice choropleth map.

Happy Mapping!

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#