OpenLayers – How to Put Content of Popup into Modal Using OpenLayers

geodjangojavascriptopenlayers

I'm trying to put the content of a OpenLayers 5 popup into a Boostrap's modal but I cannot make it.

Here the code with popup; it work fine:

.
.
.

<div id="popup" class="ol-popup">
  <a href="#" id="popup-closer" class="ol-popup-closer"></a>
  <div id="popup-content"></div>
</div>
.
.
.

<script type="text/javascript">
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');

var overlay = new ol.Overlay({
  element:  document.getElementById('popup'),
  autoPan: true,
  autoPanAnimation: {
    duration: 250
  }
});

closer.onclick = function() {
  overlay.setPosition(undefined);
  closer.blur();
  return false;
};

var map = new ol.Map({
  controls: ol.control.defaults().extend([
    new ol.control.ScaleLine({className: 'ol-scale-line', target: document.getElementById('scale-line')}),
  ]),
  layers: [
    OpenStreetMap,
    istat,
  ],
  overlays: [overlay],
  target: 'map',
    render: 'canvas',
  view: new ol.View({
    extent: boundary,
    center: center,
    zoom: 2,
        maxZoom: 20,
        minZoom: 14
  })
});

map.on('singleclick', function(evt) {

  clickFeature = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
      // console.log(feature);
      return feature;
    });

  if (clickFeature) {
    // console.log(clickFeature.getProperties().pk);
    overlay.setPosition(evt.coordinate);
     content.innerHTML =
     '<table class="table table-striped text-center">'
      + '<thead><tr><th colspan="2"><h3>Residenti stimati</h3></th></tr></thead>'
      + '<tbody>'
      +   '<tr><td colspan="1"><strong>1991</strong></td><td colspan="1">' + clickFeature.getProperties().c_1991 + '</td></tr>'
      +   '<tr><td colspan="1"><strong>2001</strong></td><td colspan="1">' + clickFeature.getProperties().c_2001 + '</td></tr>'
      +   '<tr><td colspan="1"><strong>2011</strong></td><td colspan="1">' + clickFeature.getProperties().c_2011 + '</td></tr>'
      + '</tbody>'
      +'</table>'
     }

});
</script>

Below the modal that I will use:

<div class="modal fade" id="exampleModalScrollable" tabindex="-1" role="dialog" aria-labelledby="exampleModalScrollableTitle" aria-hidden="true" id="popup">
  <div class="modal-dialog modal-dialog-scrollable" role="document">
    <div class="modal-content">

      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalScrollableTitle">Dati da area clickFeature.getProperties().c_2001</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close" id="popup-closer">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body" id="popup-content">
        <table class="table table-striped text-center">
          <thead class="">
            <tr>
              <th colspan="2">Residenti stimati</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td colspan="1"><strong>1991</strong></td>
              <td colspan="1">clickFeature.getProperties().c_1991</td>
            </tr>
            <tr>
              <td colspan="1"><strong>2001</strong></td>
              <td colspan="1">clickFeature.getProperties().c_2001</td>
            </tr>
            <tr>
              <td colspan="1"><strong>2011</strong></td>
              <td colspan="1">clickFeature.getProperties().c_2011</td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="modal-footer">
        <small class="text-muted"><em>Rielaborazione di dati da censimento ISTAT</em></small>
      </div>

    </div>
  </div>
</div>

How I can do it? I've few skills with javascript and I'm using Bootstrap 4.3.1

Best Answer

Bootstrap elements (popups, dialogs) have their own logic (methods) of showing/hiding. Initially they are hidden, they are then showed by JQuery $(element).modal('show') method, so you have to treat them differently as usual html overlays.

Instead of setting html content, you just call $(element).modal('show') method:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalScrollableTitle" aria-hidden="true">
...
</div>
var overlay = new ol.Overlay({
  element:  document.getElementById('myModal'),
  autoPan: true,
  autoPanAnimation: {
    duration: 250
  }
});

map.on('singleclick', function(evt) {
  clickFeature = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
    return feature;
  });
  if (clickFeature) {
    var element = overlay.getElement();
    overlay.setPosition(evt.coordinate);
    $(element).modal('show');
  }
});

If you want to dynamically change content of modal window, you can do it by giving id to desired elements and then changing innerHTML property of the element.