Skip to main content

Extending a custom component

In this tutorial we will see how we can customize an existing component. This tutorial is meant to be followed on a GeoGirafe instance installed by the create template.

Geogirafe comes with a lot of "core" components. One of them is the right click on the map that will open a menu with contextual information. By default, only coordinates are shown. In this tutorial we will add an extra information to it: the altitude above sea level based on a free web service.

The web service syntax is:

https://api.open-elevation.com/api/v1/lookup?locations=<LAT>,<LONG>

For instance:

https://api.open-elevation.com/api/v1/lookup?locations=46.99127,6.93749

info

You can find the final code of this tutorial here:

https://gitlab.com/geogirafe/gg-sample/-/tree/extend-existing-component

Prepare the code

  1. Make sure you have a src/components folder, if not create it.
  2. Inside src/components folder create a new folder named my-context-menu. You could name it as you want.
  3. Inside src/components/my-context-menu create a component.ts file with this content:
import { MapDefaultContextMenuComponent } from "@geogirafe/lib-geoportal/components";

class MyContextMenuComponent extends MapDefaultContextMenuComponent {}

export default MyContextMenuComponent;
  1. Define the web component in main.ts when the app is ready:
/src/main.ts
import MyContextMenuComponent from './components/my-context-menu/component';

...

girafeApp.isReady().then(() => {

// Define custom components
customElements.define('my-first-component', MyFirstComponent);
customElements.define('my-extended-component', MyExtendedComponent);
customElements.define('my-context-menu', MyContextMenuComponent);

// Remove the splash-screen
splash.end();
});
About naming webcomponents

Remember that a web component has to be named with a hyphen in it.

  1. Replace the existing <girafe-default-context-menu> with yours in index.html:
/index.html
  <girafe-app>
<header>
...
</header>
...
- <girafe-default-context-menu></girafe-default-context-menu>
+ <my-context-menu></my-context-menu>

If you run your app and the right click is working, you're now using your component even if you can't tell because we haven't add any customization yet.

  1. Create a template.html in src/components/my-context-menu directory:
src/components/my-context-menu/template.html
<p>Hello World</p>
  1. Reference it in your component:
src/components/my-context-menu/component.ts
class MyContextMenuComponent extends MapDefaultContextMenuComponent {
templateUrl = './template.html'; // override the parent template
}

Now, when you right click you should see that GeoGirafe is using your component.

  1. Let's copy the original template from the core code here: https://gitlab.com/geogirafe/gg-viewer/-/blob/main/src/components/context-menu/default-context-menu/template.html

  2. Because we overrided the html template, create a new style.css file in src/components/my-context-menu directory. Copy the content of those two CSS:

  1. Don't forget to reference it in the component:
src/components/my-context-menu/component.ts
class MyContextMenuComponent extends MapDefaultContextMenuComponent {
templateUrl = './template.html'; // overide the parent template
styleUrl = './style.css';
}
  1. Let's add a placeholder for our new height service, add a <tr> at the end of the existing <table>:
src/components/my-context-menu/template.html {2-5}
        ...
<tr>
<td>Elevation</td>
<td id="contextmenu-elevation">0</td>
</tr>
</tbody>
</table>
...
  1. Create a new property in the component:
src/components/my-context-menu/component.ts
class MyContextMenuComponent extends MapDefaultContextMenuComponent {
templateUrl = './template.html'; // overide the parent template
styleUrl = './style.css';

height: number = -1000;
}

And reference it in the template:

src/components/my-context-menu/template.html
        ...
<tr>
<td>Elevation</td>
<td id="contextmenu-elevation">${this.height}</td>
</tr>
</tbody>
</table>
...
  1. Now, let's add the logic in the component:
src/components/my-context-menu/component.ts
import { MapDefaultContextMenuComponent } from "@geogirafe/lib-geoportal/components";
import {toLonLat} from 'ol/proj';

class MyContextMenuComponent extends MapDefaultContextMenuComponent {
templateUrl = './template.html';
styleUrl = './style.css';

height: number = -1000;

async getRasterData(): Promise<void> {
const coords = toLonLat(this.mapContextMenuState.position);
const url = `https://api.open-elevation.com/api/v1/lookup?locations=${coords[1]},${coords[0]}`;
fetch(url).then(response => response.json()).then(data => {
this.height = data.results[0].elevation;
super.renderContent();
});
}

override showContextMenu(): void {
super.showContextMenu();
this.getRasterData();
}
}
warning

This is not optimal at all, we're expecting the map to be in Web Mercator, i.e. 'EPSG:3857', we don't manage a possible error and we should show a spinner while we wait from the webservice. Such improvements are out of the scope of the present tutorial.

  1. That's it! When extending an existing component, it's important to understand the core plugin so you know what you'll extend and what you need to override.