Hello, I have a geojson feed going into an Openlayers map that is created by views. In the geojson view, I am exposing a filter, outputting it as a block, and displaying that block on the end result map page.

The default value of the filter is passed to the map, however when I update the filter to a value different than the default, the page is redirected to the text-based json output instead of changing the content inside of the map.

So basically my question is: how can I get an exposed filter to work with geojson and openlayers in views?

Thanks in advance for any help that anyone can provide.

Comments

basvredeling’s picture

Issue summary: View changes

It seems asynchronously loaded view_geojson layers do not inherit the exposed filter values. That includes full text search filters.

What happens is this:

  1. openlayers map page is requested
  2. map is prepared (including url parameters from exposed filters)
  3. layer definitions are loaded
  4. map is rendered
  5. geojson layers are requested by statically defined url (eg. without url parameters)
  6. exposed filters are applied to the map page but not to the geojson layers (since these are requests to completely different paths).

I implemented a workaround for the "search" exposed filter by altering the map definition like so:

/**
 * Change the urls of the geojson feeds to include exposed "search" filter.
 */
function MYMODULE_openlayers_map_alter(&$map) {
  $query = drupal_get_query_parameters();
  foreach ($map['layers'] as $layer_id => $layer) {
    if ($layer_id == 'GEOJSON_LAYER_ID') {
      $map['layers'][$layer_id]['url'] .= '?search=' . urlencode($query['search']);
    }
  }
}

Replace search by your exposed filter id. And replace MYMODULE / GEOJSON_LAYER_ID too.

I don't like this solution. There should be an openlayers native solution which passes exposed filters to geojson layers. This solution also assumes that you have the same exposed filter id's configured on all geojson feed displays as well as on the openlayers map display itself.

bendev’s picture

Hello,

here is how I proceeded with OPL v3 (thanks to Pol)



function map_acvc_openlayers_object_preprocess_alter(&$build, $context) {

  if ($context->machine_name == 'GEOJSON_LAYER_ID') {
    if (!isset($context->preprocess)) {
      $query = drupal_get_query_parameters();
      $param = '?';
      foreach ($query as $key => $value) {
        if ((!empty($value)) && ($value != 'All')) {
          $param .= urlencode($key) . '=' . urlencode($value) . "&";
        }
      }
      $context->options['url'] .= $param;
    }
    $context->preprocess = TRUE; //only process once)
  }
}

It works fine excepted for the handling of the 'All' value which doesn't work.
if I go to the geojson feed url and i remove the filter of the url (=ALL) . I get all results.
I tried with filter=ALL, filter=& and without filter...
not working so far

droces’s picture

Bendev's code worked for me, solving the OL Map respecting exposed filters, but with two modifications:
GEOJSON_LAYER_ID needed to be my GEOJSON_SOURCE_ID
and…
$context -> options['url'] .= $param;
Needed to be:
$context -> setOption('url', $context -> getOption('url') . $param);

However, I was still getting a page of code when I used the exposed filters. That was because the exposed filters form's #action was pointing back to that feed's url. So basically I needed a hook_form_alter to post the exposed filters form to the current page:

/**
 * Implements hook_form_FORM_ID_alter().
 */
function casa_map_mgt_form_views_exposed_form_alter(&$form, &$form_state, $form_id) {
  $feed_url = base_path() . 'browse/pictures/feed.geojson';

  if (drupal_match_path($form['#action'], $feed_url)) {
    $form['#action'] = base_path() . 'browse/pictures/map'; // Make it post to the current url
  }
}
jlsevillano’s picture

I quite confuse where can i do it (patch).

My GeoJSON view is: tramos-json
My Page with exposed filter: tramos-mapa

Have i to add, where, which module?

Thanks

jlsevillano’s picture

I created a custom module, but when i filter:

Notice: Undefined property: Drupal\openlayers\Plugin\Style\Circle\Circle::$machine_name in line 5

if ($context->machine_name == 'GEOJSON_SOURCE_ID') {

what's wrong?

robertwb’s picture

Project: Views GeoJSON » Openlayers
Version: 7.x-1.x-dev » 7.x-3.x-dev
Related issues: +#2381165: Re-thinking Leaflet GeoJSON and exposed filters

I think that this is more appropriately an OL question / there is a similar thread for Leaflet which supplies a patch to enable additional filters to be used when accessing Views GeoJSON data sources. Changing project -- apologies if I am misreading this.

basvredeling’s picture

jesus.soto’s picture

I have recently working using exposed filters on ol3 geojson views. I hope I can help you.

1- First at all, create a Geojson view:
You need create an OpenLayer data view, add filtering criteria fields and finally over the view add a geojson feed
Once you have created the view, test it using the url directly.

/geojsonv2 (without parameters)
/geojsonv2/param1/param2 (using parameters)

Important: The administrative identifier of each filter must be the same as in the view that contains the exposed form.

2- Get parameters from exposed form:

You must build an url that includes the parameters selected in the exposed form. Example:

  function getParamsFromExposedForm() {
        var params = "";
         //** MULTISELECT FIELD campaingtype .. checkboxes **// 

        $('input[name="field_campaingtype_value[]"]').each(function (i, selected) {
            if (selected.checked)
                params += ((params === "") ? "/" : "+") + $(selected).val();
        });

        // .. another exposed form filters 

        return params;
    }

3- Ajax Request and Update
Finally, launch the ajax request using the url that includes the parameters from the exposed form.
When the information is received in geojson format, load all features in the specific source of the map.

 $('#' + idmapctl).append(over);
                $.ajax(urlGeoJSON).then(function (response) {
                    // ** Load features ** //
                    var formatGJSON = new ol.format.GeoJSON();
                    var features = formatGJSON.readFeatures(response,
                            {featureProjection: 'EPSG:3857'});
                    mapa.sources.CommercialCampaigns_filter.clear();
                    mapa.sources.CommercialCampaigns_filter.addFeatures(features);
                    $('#overlay-canvas').remove();
                });                    

   function updateCommercialCampaignsSources() {
            //** Get the map component **/(
            var idmapctl = $('.openlayers-map').attr('id');
            map = Drupal.openlayers.getMapById(idmapctl);

            //** Build geojson url **//
            var params = getParamsFromExposedForm();
            var urlGeoJSON = "/campaigns/geojsonv2" + params;

            //** Define preloader **//
            var over = '<div id="overlay-canvas">' +
                                  '<img id="loading" class="overlay-canvas-center" src="../img/map_preloader.gif">' +
                            '</div>';

             //** Launch URL request **// 
                $('#' + idmapctl).append(over);
                $.ajax(urlGeoJSON).then(function (response) {
                    // ** Load all features received on map source CommercialCampaigns_filter **//
                    var formatGJSON = new ol.format.GeoJSON();
                    var features = formatGJSON.readFeatures(response,
                            {featureProjection: 'EPSG:3857'});
                    map.sources.CommercialCampaigns_filter.clear();
                    map.sources.CommercialCampaigns_filter.addFeatures(features);
                    $('#overlay-canvas').remove();
                });                    
    }

Ajax changes in an exposed form should update the map if the view is linked to a source.
It would be great if this type of functionality were incorporated natively on this great drupal module.