11

I'm currently working on an Angular 6 application that uses ngx-leaflet for using leaflet. We want to be able to create a base component that can be customized by adding directives to it. Basically the same pattern that is used when using draw capabilities using leafletDraw. But these directives should be more abstract then the leaflet and leafletDraw directives.

Currently we ended up with the following template that is used in our "base component"

<div class="map" leaflet [leafletOptions]="options" [leafletLayers]="layers" [leafletOptions]="options" leafletDraw [leafletDrawOptions]="drawOptions" poiSelection [poiSelectionOptions]="selectionOptions"
poiSelection [trackPlaybackOptions]="trackOptions">
</div>

As you can see this can end up in a big wall of directives on different abstraction levels.

I rather have this :

<app-our-nice-map poiSelection [poiSelectionOptions]="selectionOptions" [trackPlaybackOptions]="trackOptions">
</app-our-nice-map>

And the template for the OurNiceMapComponent component would look like this :

<div class="map" leaflet [leafletOptions]="options" [leafletLayers]="layers" [leafletOptions]="options">
</div><!-- this is here because Stackoverflow doesn't like single div /-->

There's two challenges with this.

  1. Finding a way on how a higher level directive can be interacting/configuring (poiSelection) with a lower level directive (leafletDraw).
  2. How to add a directive dynamically. As you can see in the above template for OurNiceMapComponent I didn't add leafletDraw, because that is only used by a specific higher level directive.

So the question is, how to create these "higher order directives".

Ricardo Rocha
  • 14,612
  • 20
  • 74
  • 130
Saab
  • 981
  • 3
  • 11
  • 34
  • AFAIK it's not possible to dynamically mount directives. If number of inputs that will be used with this component is finite I would just redeclare those input in OurNiceAppComponent and based on which inputs were provided by user, render div with corresponding directive(s) and inputs. – Wilhelm Olejnik Aug 02 '18 at 20:08
  • 1
    If you are asking how to dynamically add directives, the answer is you can't as of yet, and this question is a duplicate of this question: https://stackoverflow.com/questions/41298168/how-to-dynamically-add-a-directive – bodorgergely Aug 03 '18 at 20:35
  • Nice upvote ratio :-) 115 views and 10 upvotes :-) – Simon_Weaver Aug 21 '18 at 22:21

2 Answers2

1

There is workaround, you can use ngSwitch/ngIf and render leaflet with correct set of directives depending on component options.

kemsky
  • 14,727
  • 3
  • 32
  • 51
0

If each of your bindings are actually directives and not just input/output bindings, you can nest the DOM structure and still inject the Leaflet directive into your directive. ngx-leaflet already does this for the various directives that implement most of its functionality.

What I mean is, you can do the following:

<div class="map" leaflet [leafletOptions]="options" [leafletLayers]="layers">
  <div *ngIf="someCondition"
       leafletDraw [leafletDrawOptions]="drawOptions"></div>
  <div *ngIf="someOtherCondition"
       poiSelection [poiSelectionOptions]="selectionOptions"></div>
</div>

Under the hood, the leaflet directive is injected into the leafletDraw directive (using Angular dependency injection). And, I'd assume it's the same for your directive.

ngx-leaflet also allows you to do this for adding/removing single layers. It's the same technique where leafletLayer is actually a directive into which the leaflet directive is injected.

<div class="map" leaflet [leafletOptions]="options">
  <div [leafletLayer]="layer1"></div>
  <div [leafletLayer]="layer2"></div>
  <div [leafletLayer]="layer3"></div>
</div>
reblace
  • 4,115
  • 16
  • 16