> For the complete documentation index, see [llms.txt](https://runette.gitbook.io/alcm/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://runette.gitbook.io/alcm/custom-controls.md).

# Custom Controls

As you might expect, this same method can be used to add custom controls. The list of issues is similar, with the main difference being that 'import the code' is replaced by 'create the ui'. This topic also covers CSS. A template `component.ts` is shown at the bottom of the page and can be copied.

{% hint style="info" %}
The proforma template does NOT accept an options object! We are in the Angular paradigm and should be idiomatic - therefore the config options should be passed as individual parameters in the directive and not as an options object. The only parameter in the `L.Control` default options object is `position` which is dealt with in the tempate. Since we have no other legacy code, we should do everything new in Angular.
{% endhint %}

#### Create Typings

No typings are required for the basic control, since the @types/leaflet definition cover the basic `L.Control` class.

Addition typings are only required if you want to add methods to the control, and as discussed above any additional functionality should really be done in the component typescript.

#### Create the UI

The UI for the control is defined in the HTML for the component (in the standard cae that is `./xxx.component.html` ).

There should be an element for the control (usually a DIV) that defines the UI. This is passed to the map when the control is added to the map. This element must have the id that is used in the component code - in the template this is 'custom' but that should be changed to the name of your control.

{% hint style="info" %}
In most cases, the element needs to have a width or min-width defined. Without this, the control will not be displayed.
{% endhint %}

{% hint style="info" %}
Note that since for the custom control the HTML is created in the Angular component, it is part of the CSS encapsulation mechanisms. Therefore, the CSS for the UI should be included in the the CSS definition for the component (in the standard case this is `./xxx.component.css .`
{% endhint %}

#### Create a Directive

This is set in the component. The template would, for instance, create the directive :

```markup
<app-custom-control [position]='bottomright' [map]='map'></app-custom-control>
```

#### Add the Control to the Map

The template implements the same mechanism for adding the control to the map as proposed for existing controls above.

There should not be a need to do anything in addition to the basic template.

#### Interact with the Control&#x20;

The scope for interaction with the control is, of course, as large as HTML and Angular allow!

However, there are few points to remember.

{% hint style="info" %}
You can create map event handlers either in the leaflet `.onAdd` code or in the typescript. Since the lifecycle of the control is the same as a the lifecycle of the component, I prefer to do it all in the typescript to keep things clean.

If you create a listener, remember to tear it down either in `.onRemove` or `ngOnDestroy` respectively.
{% endhint %}

{% hint style="info" %}
&#x20;As described in the [ngx-leaflet documentation](https://github.com/Asymmetrik/ngx-leaflet#a-note-about-change-detection), the leaflet map is running outside of Angular change detection to avoid a huge overhead of events swamping Angular.

This means that many events used to update the control, like for instance clicks on the map, may not change as expected.

In this case, you will have to manually trigger change detection after the data is updated. There is a worked example of this at the bottom of this page.
{% endhint %}

## Template Code

The basic framework for a new custom control component is shown below.&#x20;

```typescript
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import {Map, Control, DomUtil, ControlPosition} from 'leaflet';

@Component({
  selector: 'app-custom-control',
  templateUrl: './custom-control.component.html',
  styleUrls: ['./custom-control.component.css']
})
export class CustomControlComponent implements OnInit, OnDestroy {
  private _map: Map;
  public custom: Control;
  @Input() position: ControlPosition;

  constructor() { 
  }

  ngOnInit() {
  }

  ngOnDestroy() {
    this._map.removeControl(this.custom)
  }

  @Input() set map(map: Map){
    if (map){
      this._map = map;
      let Custom = Control.extend({
        onAdd(map: Map) {
          return DomUtil.get('custom');
        },
        onRemove(map: Map) {}
      });
      this.custom=new Custom({
          position: this.position
        }).addTo(map);
    }
  }
  get map(): Map {
    return this._map
  }

```

{% file src="/files/-LzgRRSp7yzzJF7P1XkC" %}
Custom Control Component Template
{% endfile %}

{% hint style="info" %}
Remember to change the names that are based on "custom" and "Custom" to the name of your custom control.
{% endhint %}

## Example

To see the description of a worked example, see :

{% embed url="<https://medium.com/runic-software/adding-custom-controls-to-you-angular-map-2056f7711746>" %}

The demo code is shown in this stackblitz. Click anywhere on the map to see the control update.&#x20;

{% embed url="<https://stackblitz.com/edit/angular-leaflet-custom>" %}
