0

I'm working on a leaflet wagtail block integration.

https://github.com/frague59/wagtail-leaflet

I've difficulties with the widget rendering when I add the new block into the stream : nothing displays. The widget, from django-leaflet / django-geojson, involves the setting of geojson parameters 'window wide', which is not reflected in template instanciation.

In my leaflet/widget.html:

<script type="text/javascript">
    {% block vars %}var {{ module }} = {};
    {{ module }}.fieldid = '{{ id_css }}';
    {{ module }}.modifiable = {{ modifiable|yesno:"true,false" }};
    {{ module }}.geom_type = '{{ geom_type }}';
    {{ module }}.srid = {{ map_srid }};
    {% endblock vars %}
       function {{ id_map_callback }}(map, options) {
        window.LEAFLET_DATA['{{ module }}'].store_class = {{ field_store_class }};
        (new {{ geometry_field_class}}(window.LEAFLET_DATA['{{ module }}'])).addTo(map);
        {% block callback %}{% endblock callback %}
    };

    {% if target_map %}
        window.addEventListener('map:init', function (e) {
            var target_map = e.detail.map;
            target_map.on('map:loadfield', function (me) {
                if (me.fieldid == 'id_{{ target_map }}') {
                    setTimeout(function () {
                        {{ id_map_callback }}(target_map, e.detail.options);
                    }, 0);
                }
            });
        }, false);
    {% endif %}
</script>

From text/template element:

<script type="text/javascript">
    var geodjango___prefix___value = {};
    geodjango___prefix___value.fieldid = '__prefix__-value';
    geodjango___prefix___value.modifiable = true;
    geodjango___prefix___value.geom_type = 'Geometry';
    geodjango___prefix___value.srid = 4326;


    function __prefix___value_map_callback(map, options) {
        geodjango___prefix___value.store_class = L.FieldStore;
        (new L.GeometryField(geodjango___prefix___value)).addTo(map);

    };

</script>

The Streamfield block API does not mention clearly this use case.

Do you have a working block example with this kind of block ?

Thanks !

frague
  • 189
  • 1
  • 10
  • Please provide a [minimal, complete and verifiable](https://stackoverflow.com/help/mcve) code example. – gasman May 04 '17 at 11:10
  • https://github.com/makinacorpus/django-leaflet/issues/189 – frague May 04 '17 at 11:28
  • @gasman Relevant code in my repository : https://github.com/frague59/wagtail-leaflet – frague May 04 '17 at 11:31
  • Nobody here is going to dig through your entire project to find out what the problem is. As explained at https://stackoverflow.com/help/mcve, you need to reduce your code to the smallest example that demonstrates the problem. – gasman May 04 '17 at 12:50

1 Answers1

0

Requirements:

django-leaflet
django-geosjon
jsonfield 

The block definition: uses the leaflet widget from django-leaflet / django-geosjon

class GeoJSONBlock(FieldBlock):
    geom_type = 'POINT'

    def __init__(self, required=True, help_text=None, max_length=None, min_length=None, **kwargs):
        if self.geom_type is None:
            raise NotImplemented('You are attempting to use ``GeoJSONBlock`` directly, which *WILL* not work !')

        self.field = GeoJSONFormField(required=required,
                                      help_text=help_text,
                                      max_length=max_length,
                                      min_length=min_length,
                                      geom_type=self.geom_type)
        super(GeoJSONBlock, self).__init__(**kwargs)

    def render_form(self, value, prefix='', errors=None):
        """
        Renders ``edit`` form

        :param value: current value
        :param prefix: prefix of the form item
        :param errors: Validations errors
        :returns: HTML Fragment
        """
        logger.debug('MapBlock::render_form() value = %s', value)
        rendered = super(GeoJSONBlock, self).render_form(value=value, prefix=prefix, errors=errors)
        return rendered

    def render(self, value, context=None):
        """
        Renders the widget in the web site

        :param value: current value
        :param context: Additional render context
        :returns: HTML Fragment
        """
        logger.debug('MapBlock::render() value = %s', value)
        rendered = super(GeoJSONBlock, self).render(value=value, context=context)
        return rendered

    @property
    def media(self):
        return forms.Media(
            js=['wagtailleaflet/leaflet_init.js', ]
        )

    def js_initializer(self):
        """
        JS function to launch on start'up
        :returns: JS function name, from ``wagtailleaflet/leaflet_init.js``
        """
        output = 'drawMap'
        logger.debug('MapBlock::js_initializer() output = %s', output)
        return output

        def html_declarations(self):
            output = render_to_string('wagtailleaflet/leaflet_forms.html')
            return output

Usage:

from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel
from wagtail.wagtailcore.fields import StreamField
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore import blocks
from wagtailleaflet.blocks import GeoJSONPointBlock

class DemoPage(Page):
    """
    Simple demo page 
    """
    body = StreamField([('text', blocks.RichTextBlock()),
                        ('map', GeoJSONPointBlock()), ])

    content_panels = Page.content_panels + [StreamFieldPanel('body')]

I've found that the problem comes from the leaflet implementation, which uses slugify (set the id to lower) to create the id, which breaks the __PREFIX__ replacement in sequence.js on block initialization.

It's a bit complicated to re-produce, that's why I did put the link to my repo with a demo wagtail project.

frague
  • 189
  • 1
  • 10