import { Directive , DoCheck , Input , IterableDiffer , IterableDiffers , NgZone , OnDestroy , OnInit } from '@angular/core' ; import { Layer } from 'leaflet' ; import { LeafletDirective } from '../core/leaflet.directive' ; import { LeafletDirectiveWrapper } from '../core/leaflet.directive.wrapper' ; /**
 * Layers directive
 *
 * This directive is used to directly control map layers. As changes are made to the input array of
 * layers, the map is synched to the array. As layers are added or removed from the input array, they
 * are also added or removed from the map. The input array is treated as immutable. To detect changes,
 * you must change the array instance.
 *
 * Important Note: The input layers array is assumed to be immutable. This means you need to use an
 * immutable array implementation or create a new copy of your array when you make changes, otherwise
 * this directive won't detect the change. This is by design. It's for performance reasons. Change
 * detection of mutable arrays requires diffing the state of the array on every DoCheck cycle, which
 * is extremely expensive from a time complexity perspective.
 *
 */ @ Directive ( { selector : '[leafletLayers]' } ) export class LeafletLayersDirective implements DoCheck , OnDestroy , OnInit { layersValue : Layer [ ] ; layersDiffer : IterableDiffer < Layer > ; @ Input ( 'leafletLayers' ) set layers ( v ) { this . layersValue = v ; this . updateLayers ( ) ; } get layers ( ) : Layer [ ] { return this . layersValue ; } private leafletDirective : LeafletDirectiveWrapper ; constructor ( leafletDirective , private differs , private zone ) { this . leafletDirective = new LeafletDirectiveWrapper ( leafletDirective ) ; this . layersDiffer = this . differs . find ( [ ] ) . create < Layer > ( ) ; } ngDoCheck ( ) { this . updateLayers ( ) ; } ngOnInit ( ) { this . leafletDirective . init ( ) ; this . updateLayers ( ) ; } ngOnDestroy ( ) { this . layers = [ ] ; } /**
     * Update the state of the layers.
     * We use an iterable differ to synchronize the map layers with the state of the bound layers array.
     * This is important because it allows us to react to changes to the contents of the array as well
     * as changes to the actual array instance.
     */ private updateLayers ( ) { const map = this . leafletDirective . getMap ( ) ; if ( null != map && null != this . layersDiffer ) { const changes = this . layersDiffer . diff ( this . layersValue ) ; if ( null != changes ) { this . zone . runOutsideAngular ( ( ) => { changes . forEachRemovedItem ( ( c ) => { map . removeLayer ( c . item ) ; } ) ; changes . forEachAddedItem ( ( c ) => { map . addLayer ( c . item ) ; } ) ; } ) ; } } } }