Custom popups in Geoserver

Custom popups in Geoserver

When we upload any layer to Geoserver, we can check the data on click by going in to Layer preview and display layer as Openlayers. Once we click on feature, Geoserver returns information table as following.

No alt text provided for this image

This is fine for testing purpose, but what about using this in production ready app? There are bunch of things that you may think when you look at this

  • How can I remove fid? After all that is not the column we have in original file
  • How can I change default colour or style
  • How can I load images instead of showing raw URLs?
  • How can I add my own custom information in popup?

Till now, to solve all of these problems I was using following hack.

Instead of loading this HTML response in my app, I was requesting data in GeoJSON and then I was styling it in my HTML.

But that means if I have to use same layer in some another app, I will have to style the popup again. Frustrating right??

GetFeatureInfo Templates

Geoserver allows us to overwrite default Geoserver feature info template. These templates are written in Freemaker which is a template engine for JAVA. WAIT WAIT!! Before you close the blog to watch another cat video, I want to tell you that I also don't know/like JAVA. But freemaker is easy to learn ( at least to solve our purpose of creating custom template in Geoserver)

By Default, Geoserver uses 3 templates for HTML output.

  1. header.ftl
  2. content.ftl
  3. footer.ftl

Freemaker files has extension of .ftl , these files needs to be places in the Data Directory of Geoserver.

If you need to change behaviour of all layers in the Geoserver, you can simply create templates folder in data directory and put .ftl files in it.

Remember, Names of the files should be exactly same

Creating Custom Templates

Header template

For this exercise we'll take default layer in Geoserver. If your Geoserver is running, hit following URL

https://localhost:8080/geoserver/topp/wms?service=WMS&version=1.1.0&request=GetMap&layers=topp%3Astates&bbox=-124.73142200000001%2C24.955967%2C-66.969849%2C49.371735&width=768&height=330&srs=EPSG%3A4326&styles=&format=application/openlayers

Once opened, turn on Inspect Element and hover on the result table generated by clicking on any of the feature. There you will see that , HTML is generating a <table> tag with class name as featureInfo .Inside the table tag we have various tags such as <caption> <th> <tr> <td> <tbody> .In this exercise, we'll focus on keeping this tags same but only updating class information of it.

Now head over to <GeoServer_data_dir>/templates and create new file header.ftl. For this blog, we'll try to create a table which looks like this

No alt text provided for this image
I know it's ugly!!

To do this, we can use the featureInfo class and sibling CSS Selector . This file is exactly like HTML file but it ends at open body tag.

<html>
  <head>
    <title>Modified Geoserver template</title>
  </head>
  <style type="text/css">
        .featureInfo{
            background-color: beige;
        }
        .featureInfo th {
            background-color: black;
            color: chartreuse;
        }
        .featureInfo  td {
            color: slateblue;
        }
  </style>
  <body>        

Note : headers.ftl file will always end with open body tag. no need to close body tag and html tag

Once you add the code and restart the Geoserver, head back to layer preview using same link

No alt text provided for this image

Footer template

To create custom footer, create new file in <GeoServer_data_dir>/templates and name if footer.ftl. Format of this file will be as follows


 <#--
Add custom code here
-->
 </body>
</html>        

For exercise, we'll simply write our name in footer.

 <h2> GeoServer maintained by - Krishna Lodha </h2>
 </body>
</html>        

Again restart Geoserver and hit the link

No alt text provided for this image

Content template

Content will be little bit complicated compared to other two, as this will require us to write conditions, parameters, etc.

For this exercise, we'll try to do following things

  1. Remove fid column
  2. Remove Layer name
  3. Add new column on the fly stating population density per km2

This will help you understand the logic we should use while creating such file.

  • To remove layer name, we'll simply omit the type.name param, which is generally available by default. Type denotes layer and information such as name, description, CRS, Native CRS, metadata and much more.
  • Features represent all the features that we clicked on. If you click on location where multiple features are available, Geoserver shows data of all features. This Features list can be looped through, to extract each feature.
  • Further each Feature has attributes, which contains column name, values,etc.. Apart from it, it also contains information such as isGeometry (which returns as true/false, based on if that column is geometry column or not) , so to create our custom table we can loop through the list of features and then in each feature, we can loop through all the attributes. In this second loop, we can then add our custom code of population density.

You can read more about available data models here

Ultimately the content.ftl file will look like this


<table class="featureInfo" >
    <tr>
  <#list type.attributes as attribute>
    <#if !attribute.isGeometry>
      <th >${attribute.name}</th>
    </#if>
  </#list>
  <th >Population Density</th>
    </tr>
  


  <#list features as feature>
  <#assign area = 0>
  <#assign pop = 0>
      <tr>
   
    <#list feature.attributes as attribute>
      <#if !attribute.isGeometry>
        <td>${attribute.value}</td>
      </#if>
      <#if attribute.name == 'LAND_KM'>
      <#assign area = attribute.value?number>
      </#if>
      <#if attribute.name == 'PERSONS'>
      <#assign pop = attribute.value?number>
      </#if>
    </#list>
    <td>${(pop/area)} / KM<sup>2</sup></td>
    </tr>
  </#list>
  </table>
  <br/>        

And we'll have something like this

No alt text provided for this image

Similar to this we can add conditions for showing images.

No alt text provided for this image

We can also use external libraries such as bootstrap in the templates.

header.ftl

<html>
  <head>
    <title>GeoServer GetFeatureInfo output</title>
  </head>
  <link rel="stylesheet"  integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">


  <style type="text/css">
    .featureInfo{
        background-color: beige;
    }
    .featureInfo th {
        background-color: black;
        color: chartreuse;
    }
    .featureInfo  td {
        color: slateblue;
    }
  </style>
  <body>        

footer.ftl

<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
 </body>
</html>        

content.ftl

<table class="table table-bordered" >
     <thead class="thead-dark">
    <tr>
  <#list type.attributes as attribute>
    <#if !attribute.isGeometry>
      <th >${attribute.name}</th>
    </#if>
  </#list>
  <th >Population Density</th>
    </tr>
</thead>
  
<tbody>
  <#list features as feature>
  <#assign area = 0>
  <#assign pop = 0>
      <tr>
   
    <#list feature.attributes as attribute>
      <#if !attribute.isGeometry>
        <td>${attribute.value}</td>
      </#if>
      <#if attribute.name == 'LAND_KM'>
      <#assign area = attribute.value?number>
      </#if>
      <#if attribute.name == 'PERSONS'>
      <#assign pop = attribute.value?number>
      </#if>
    </#list>
    <td>${(pop/area)} / KM<sup>2</sup></td>
    </tr>
  </#list>
</tbody>
  </table>
  <br/>        

It will create table with bootstrap css

No alt text provided for this image
No alt text provided for this image

The Problem

Even though this template is working fine with this layer, if you try to open another layer and check the response, Geoserver will through error.

No alt text provided for this image

It's because columns LAND_KM , PERSONS does not exist. To solve this issue we'll have to understand logic of adding template files in directory. The hierarchy in which Geoserver looks for template file is as follows

  1. GEOSERVER_DATA_DIR/workspaces/<workspace>/<datastore>/<featuretype>/content.ftl
  2. GEOSERVER_DATA_DIR/workspaces/<workspace>/<datastore>/content.ftl
  3. GEOSERVER_DATA_DIR/workspaces/<workspace>/content.ftl
  4. GEOSERVER_DATA_DIR/workspaces/content.ftl
  5. GEOSERVER_DATA_DIR/templates/content.ftl

So if we decide to move files we created in GEOSERVER_DATA_DIR/workspaces/topp/states_shapefile/states/

folder and restart the Geoserver, we'll see that the style is only now visible in states and not in any other layer

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

Similar to HTML, We can also create custom template for GeoJSON. Please write in comments if you want blog for GeoJSON.

CHESTER SWANSON SR.

Realtor Associate @ Next Trend Realty LLC | HAR REALTOR, IRS Tax Preparer

2 年

Love this.

要查看或添加评论,请登录

Krishna Lodha的更多文章

  • How to Generate Contour on the fly on GeoServer

    How to Generate Contour on the fly on GeoServer

    Digital Elevation Models (DEM) are crucial for terrain analysis, and contour lines are one of the best ways to…

    1 条评论
  • 5 Python Libraries for Earth Observation

    5 Python Libraries for Earth Observation

    Earth observation has become a cornerstone of the GIS industry, driven by the exponential growth in satellite missions…

    2 条评论
  • Digital Terrain Models in GIS: A Practitioner’s Guide to DSM, DTM, and DEM

    Digital Terrain Models in GIS: A Practitioner’s Guide to DSM, DTM, and DEM

    Picture yourself flying over a city in a helicopter. Looking down, you see buildings piercing the sky, trees dotting…

    3 条评论
  • Get Sentinel Data within seconds in?Python

    Get Sentinel Data within seconds in?Python

    With the development of STAC specification, accessing Satellite datasets have become easy and standard approach. This…

    1 条评论
  • The Ultimate Guide of Downloading OSM Data using ChatGPT

    The Ultimate Guide of Downloading OSM Data using ChatGPT

    Open Street Map is a collaborative mapping project that aims to create a free and editable map of the world. Unlike…

    7 条评论
  • Simple way of authentication for Geoserver

    Simple way of authentication for Geoserver

    Geoserver is an amazing tool which allows users to share spatial data of vector and raster type using OGC services like…

    1 条评论
  • Extending Openlayers capabilites

    Extending Openlayers capabilites

    If you have used openlayers in the past, you know it's capabilities very well. Openlayers allows users to put…

    10 条评论
  • Editing Feature directly via Geoserver

    Editing Feature directly via Geoserver

    GeoServer, an open-source geospatial server, provides powerful capabilities for serving and managing geospatial data…

    5 条评论
  • Install Geoserver on Mac OS

    Install Geoserver on Mac OS

    I use mac for most of my development purpose, and it’s already lil scary trying to install executables and libraries…

    3 条评论
  • Install Geoserver on Windows

    Install Geoserver on Windows

    I was recently trying to install Geoserver on a windows machine, until now I was using version 2.15, which had a…

    6 条评论

社区洞察

其他会员也浏览了