NextGIS Frontend
    Preparing search index...

    Module @nextgis/control-container

    Control Container

    size version

    @nextgis/control-container is a universal library for creating and managing map controls layout.

    It provides a flexible system for placing controls in map corners, creating grouped toolbars, nested panels, and switchable controls.

    The library can be used standalone with any map engine and also serves as the foundation for framework-specific integrations:

    • Leaflet: @nextgis/leaflet-control-container
    • MapLibre GL JS: @nextgis/maplibre-gl-control-container
    • OpenLayers: @nextgis/ol-control-container

    This allows using the same control layout patterns and APIs across different map engines.

    ╭───────────────────────────────────────────╮
    │ top-left                        top-right │
    │                   MAP                     │
    │ bottom-left                  bottom-right │
    ╰───────────────────────────────────────────╯
    
    npm install @nextgis/control-container
    
    import ControlContainer, {
    createButtonControl,
    createControl,
    createControlContainer,
    createToggleControl,
    } from '@nextgis/control-container';
    const controlContainer = new ControlContainer({
    map,
    });

    controlContainer.addTo('#map');

    Available positions:

    • top-left
    • top-right
    • bottom-left
    • bottom-right
    controlContainer.append('<div>Top right</div>', 'top-right');
    
    controlContainer.append(
    '<div class="map-label">Map tools</div>',
    'top-right',
    );
    const element = document.createElement('div');
    element.textContent = 'Custom element';

    controlContainer.append(element, 'top-right');

    The order option controls the order of controls in the same position or panel.

    controlContainer.append('<div>First</div>', 'top-right', 0);
    controlContainer.append('<div>Second</div>', 'top-right', 10);

    For controls, pass order in the third argument.

    controlContainer.addControl(firstControl, 'top-right', {
    order: 0,
    });

    controlContainer.addControl(secondControl, 'top-right', {
    order: 10,
    });

    Controls are attached to the map edge by default. Controls created with bar: true use the standard outer offset automatically. Set margin: false to keep a bar control attached to the map edge. This also works for button and toggle controls.

    const panel = createControl(
    {
    onAdd() {
    return undefined;
    },

    onRemove() {},
    },
    {
    bar: true,
    margin: false,
    },
    );

    A control is an object with an onAdd method. The method returns an HTML element.

    const customControl = {
    onAdd() {
    const container = document.createElement('div');
    container.textContent = 'Custom control';
    return container;
    },

    onRemove() {},
    };

    controlContainer.addControl(customControl, 'bottom-right');

    Use createButtonControl for simple button controls.

    const button = createButtonControl({
    title: 'Action',
    html: 'Run',
    onClick() {
    console.log('Clicked');
    },
    });

    controlContainer.addControl(button, 'top-left');

    Use createControl to create a panel for other controls.

    A panel can be registered with an id when it is added to the control container. After that, other controls can be placed inside it with { inside: id }.

    const panel = createControl(
    {
    onAdd() {
    return undefined;
    },

    onRemove() {},
    },
    {
    orientation: 'vertical',
    gap: 6,
    margin: true,
    },
    );

    controlContainer.addControl(panel, 'top-right', {
    id: 'tools-panel',
    order: 20,
    });

    Then add controls inside the panel.

    const button = createButtonControl({
    title: 'Button',
    html: 'Button',
    onClick() {
    console.log('Button clicked');
    },
    });

    controlContainer.addControl(button, { inside: 'tools-panel' }, {
    order: 10,
    });
    const horizontalPanel = createControl(
    {
    onAdd() {
    return undefined;
    },

    onRemove() {},
    },
    {
    orientation: 'horizontal', // 'vertical'
    gap: 0,
    },
    );

    controlContainer.addControl(horizontalPanel, 'top-right', {
    id: 'orientated-panel',
    order: 10,
    });

    Switch controls allow only one active control in the same group and target container.

    const select = createToggleControl({
    html: {
    on: 'Select on',
    off: 'Select',
    },
    switch: 'tools',
    onClick(status) {
    console.log(status);
    },
    });

    const edit = createToggleControl({
    html: {
    on: 'Edit on',
    off: 'Edit',
    },
    switch: 'tools',
    onClick(status) {
    console.log(status);
    },
    });

    controlContainer.addControl(select, 'top-left');
    controlContainer.addControl(edit, 'top-left');
    const panel = createControl(
    {
    onAdd() {
    return undefined;
    },

    onRemove() {},
    },
    {
    orientation: 'vertical',
    gap: 4,
    },
    );

    controlContainer.addControl(panel, 'top-right', {
    id: 'switch-panel',
    });

    const identify = createToggleControl({
    html: {
    on: 'Identify on',
    off: 'Identify',
    },
    switch: 'panel-tools',
    });

    const measure = createToggleControl({
    html: {
    on: 'Measure on',
    off: 'Measure',
    },
    switch: 'panel-tools',
    });

    controlContainer.addControl(identify, { inside: 'switch-panel' }, {
    order: 10,
    });

    controlContainer.addControl(measure, { inside: 'switch-panel' }, {
    order: 20,
    });

    Use different switch names for independent groups.

    const draw = createToggleControl({
    html: 'Draw',
    switch: 'edit-tools',
    });

    const erase = createToggleControl({
    html: 'Erase',
    switch: 'edit-tools',
    });

    const info = createToggleControl({
    html: 'Info',
    switch: 'view-tools',
    });
    const measure = createToggleControl({
    html: {
    on: 'Measure on',
    off: 'Measure',
    },
    switch: 'tools',
    disableOnSecondClick: true,
    });
    panel.onSwitchChange((event) => {
    console.log(event.group);
    console.log(event.status);
    console.log(event.activeControl);
    });
    const asyncControl = createToggleControl({
    html: {
    on: 'Enabled',
    off: 'Disabled',
    },
    switch: 'layers',
    async onClick(status) {
    await Promise.resolve(status);
    },
    });

    Need to fix a bug or add a feature to @nextgis/control-container? We provide custom development and support for this software. Contact us to discuss options!

    http://nextgis.com

    ControlContainer
    AddControlOptions
    ButtonControlOptions
    ControlContainerOptions
    CreateControlOptions
    HtmlToggle
    MapControl
    TitleToggle
    ToggleControl
    ToggleControlOptions
    ControlPosition
    ControlTargetPosition
    HtmlDef
    OnClick
    OnClickAsync
    OnClickSync
    OnToggleClick
    OnToggleClickAsync
    OnToggleClickSync
    ToggleStatusChangeListener
    createButtonControl
    createButtonControlContent
    createControl
    createControlElement
    createToggleControl
    createToggleControlContent
    getControlOptions
    resolveControlOptions
    setControlOptions
    default → ControlContainer