d

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.

15 St Margarets, NY 10033
(+381) 11 123 4567
ouroffice@aware.com

 

KMF

Bing Maps With Angular in a Spring Boot Application

The AngularAndSpringWithMaps project shows how to integrate Bing Maps, Angular, and Spring Boot with a Gradle build. The property data of the sites is stored with JPA in H2/PostgreSQL databases. 

The purpose of the AngularAndSpringWithMaps project is to show the site properties at different points in time. To choose the site and then choose the time and have the site properties displayed in a map. New properties can be added and deleted on the map and then persisted. This article will show how to store and display company sites.

The Backend

The site properties are stored in these Entities:

  • CompanySite -> the site that contains the properties at the location for the year. All the necessary contained entities are loaded.
  • Polygon -> a property at the CompanySite with multiple Rings; a Polygon can contain holes.
  • Ring -> a ring of location points that makes up a property or a hole in a property (could be a lake).
  • Location -> a location point of a ring.

The initial test data is provided by Liquibase with the files in this directory. For information about setting up Liquibase with Spring Boot, these articles (article 1, article 2) help a lot. For loading the initial data this article can help.

The CompanySiteRepository to get the site for the year:

In lines 2-3, the companySite with a name containing the name string and the year is selected.

The company sites are loaded with the CompanySiteService: 

In lines 2-6, empty titles or titles shorter than two characters are filtered out and the beginning and end of the year are set.

In lines 7-10, the companySite are selected from the DB and the entity tree is ordered with the orderCompanySite method.

In lines 13-18, the companySite entity locations are ordered to get the property borders. This is done in code because the locations are selected by JPA.

The REST endpoint is implemented in CompanySiteController:

In lines 1-3, the base REST endpoint is defined.

In lines 5-9, the CompanySiteService is injected with the constructor.

In lines 11-14, the REST endpoint to get a company site by title and year is defined. The variables are defined in the @RequestMapping and read in parameters with @PathVariable.

In lines 15-19, the companySites are read with the CompanySiteService and then mapped in a stream with the EntityToDtoMapper to dtos for the front-end.

In lines 20-21, the result is returned in a ResponseEntity with the HTTP status ok.

The Front-End

The documentation for Bing Maps can be found here. Bing provides types for the API. Bing Maps support the data structures polygon/ring/location that are supported in the backend. For the components Material is used.

In the package.json file, the libraries are built for Ivy postinstall and the types are added:

In line 10, the libraries are built for Ivy after the install. 

In line 19, the types for bingmaps are added for TypeScript.

The map is displayed in the CompanySite component with this template:

In line 2, the formGroup componentForm is set as reactive form for the component.

In lines 6-20, a <mat-form-field> wraps a <input> with a <mat-autocomplete> feature. The <input> is connected to the formControl companySite. The <mat-autocomplete> is connected to the input with #auto and the matAutocomplete property. The <mat-options> of the <mat-autocomplete> show the titles of the companySiteOptions observable. That is all that is needed for a typeahead with Material components.

In lines 23-26, <mat-slider> is added to select the year it starts with 1970 and ends with 2020 and is connected to the formControl sliderYear.

In lines 27-30, a <span> is added to display the year of the slider.

In line 36, a <div> is added with #bingMap to provide the container that displays the map.

The CompanySite component is set up like this:

In lines 1-6, the Component is defined with the needed live cycle callback interfaces.

In lines 7-8, the elementRef for the map is injected.

In line 11, the map property is defined.

In line 14, the observable for the autocomplete input is defined.

In lines 15-19, the reactive form with initial values is created. 

In line 25, the containerInitSubject is created that emits when the initial values are available.

In lines 26-28, the hot subscriptions are defined to be unsubscribed in the onDestroy.

In lines 30-34, the needed elements get injected in the constructor. The FormBuilder has been used to create the reactive form.

To read the companySite data the CompanySiteService is used: 

This is a simple service that uses the HttpClient to get the matching CompanySites for the title and year.

The BingMapsService is used to load the newest version and initialize the mapcontrol component from Bing:

((resolve, reject) => {
(window)[callBackName] = () => {
this.initialized = true;
resolve(true);
};
script.onerror = (error: Event) => {
console.log(error);
reject(false);
};
});
return from(scriptPromise);
}
}” data-lang=”application/typescript”>

In lines 1-5, the singleton service is defined with the initialized property set to false.

In lines 8-10, it checks if Bing Maps has already been initialized.

In lines 11-12, a unique callback name for the successful load of Bing Maps is created and the URL with the name and apiKey is set.

In lines 13-19, the new script tag in the document head is created.

In lines 20-29, the scriptPromise is setup. The Bing Maps callback resolves and sets initialized to true. The onerror script callback logs and rejects.

In line 30, an observable is created from the promise and gets returned.

The CompanySite is initialized like this: 

ngOnInit Method

In lines 8-17, the mat-autocomplete is the service call that gets the options for the auto complete. The reactive form refreshes the options on value change and debounces it. Then there is a minimum validity check and either the matching companySites are retrieved from the server or the empty observable is returned.

In lines 18-29, the newly selected companySites of the auto complete are debounced and filtered for selected sites. Then they are retrieved from the server and filtered for empty responses. Then the updateMap method is called to display the new site on the map.

In lines 30-41, the values of the mat-slider component are debounced and there is a filter that ensures that it only works if a companySite is selected. Then the companySites for the selected year are retrieved from the server and are filtered for empty responses. Then the updateMap method is called to display the site at the selected year on the map.

In lines 42-50, forkJoin is used to send the requests for the MainConfigration with the Bing Maps key and the initial CompanySite concurrently. The responses come in an array where the mainConfiguration is in first element and the companySites in the second. They are set in the property and in the Container object. The Container object is send with next in the containerInitSubject.

ngAfterViewInit Method

In the ngAfterViewInit method, the the map of bing is initialized because the view has to be available for it. In lines 54-59, the containerInitSubject is used to make sure the companySite and the configuration is send. A validation check is done. Then flatMap is used with the BingMapsService is used to initialize the map. 

In lines 64-73, the IMapLoadOptions interface is created with the current center for the new Map.

In lines 73-75, the new map is created on the bingContainer property with the IMapLoadOptions.

In line 77, the companySite is set in the form.

In lines 78-79, the the polygons are updated for the map.

In lines 80-81, the listener for clicks on the map is set. 

ngOnDestroy Method

In lines 86-90, the containerInitSubject gets cleared with next and the hot subscribtions are unsubscribed. The the map gets disposed.

updateMap Method

In line 93, it is checked that the map is initialized. 

In lines 94-98, the IMapLoadOptions of the Bing Map are updated.

In lines 99-100, the entities of the map are cleared and the polygons are recreated.

Conclusion

Spring Boot with JPA and H2/Postgresql makes storing map data easy. 

Bing Maps provides nice types for the TypeScript interface. That makes it much easier to use the API and with the types the API is easy to understand. Integrating Bing Maps was pretty straight forward. It needs to be added in the ngAfterViewInit because the ElementRef has to be available. The Angular Material components are easy to use and to integrate with RxJS and reactive forms. 

The next article will describe how to to add and remove properties to a companySite by clicking on the map.

Finally

The testdata for the year 2020 shows the property of a factory where the product of the article image is made.

Credit: Source link

Previous Next
Close
Test Caption
Test Description goes like this