Overlay

    The overlay service provides an easy and quick way to dynamically render content in the foreground of an app. The content to be rendered, also the way it renders (e.g. placement, animations, scroll and click behaviors) are highly configurable and able to match all of the possible scenarios. The overlay service is fully integrated in the toggle directive.

    Angular Overlay Example

    Getting Started

    First we need to import the IgxOverlayService in the component and inject a reference to it in the component's constructor:

    
    import { Inject } from '@angular/core'
    import { IgxOverlayService } from `igniteui-angular`;
    
    ...
    
    export class MyOverlayComponent {
        constructor(
            @Inject(IgxOverlayService) private overlayService: IgxOverlayService
        ) {}
    }
    
    ...
    

    Displaying Content

    The overlay service can be used to dynamically display an HTMLNode or even an Angular Component by attaching it to the overlay DOM.

    After a reference to the Overlay service is established, it can be used to dynamically show/hide content. For example, we can pass an Angular Component in the attach method. This will generate a unique ID, which we can pass to the show method to display the component:

    
    // my-overlay-component.component.ts
    import { MyDynamicComponent } from '../my-dynamic-component/my-dynamic-component.component';
    
    export class MyOverlayComponent {
        private _overlayId = ''; // The unique identifier assigned to the component by the Overlay service
        ... 
        // a reference to the OverlayService is defined via @Inject in the constructor
        // under this.overlayService
    
        public showInOverlay() {
            if (!this._overlayId) {
                this._overlayId = this.overlayService.attach(MyDynamicComponent);
            }
            this.overlayService.show(this._overlayId);
        }
    }
    
    <!-- my-overlay-component.component.html -->
    <div class='content'>
    ...
        <button (click)="showInOverlay()">Show Overlay</button>
    </div>
    

    If we want to pass an already existing ElementRef from the page to the IgxOverlayService, we can do it as follows:

    <!-- my-overlay-component.component.html -->
    <div class='content'>
        <button (click)="showInOverlay()">Show Overlay</button>
    </div>
    <div>
        <img #exampleImage width='200px' src='../assets/example.png' title='Click Me!'>
    </div>
    
    // my-overlay-component.component.ts
    import { Inject, ViewChild } from '@angular/core'
    export class MyOverlayComponent {
        private _overlayId = ''; // The unique identifier assigned to the component by the Overlay service
    
        @ViewChild('exampleImage', {read: ElementRef})
        private exampleImage: ElementRef;
        public showInOverlay() {
            if (!this._overlayId) {
                this._overlayId = this.overlayService.attach(this.exampleImage);
            }
            this.overlayService.show(this._overlayId);
        }
    }
    

    The Overlay Service's attach() method has two overloads:

    • attach(element, settings?)
    • attach(component, settings?, moduleRef?)

    The first parameter in both overloads is mandatory and represents the content that will be shown in the overlay. There are a couple of different scenarios how the content can be passed:

    • A component definition - When passing a component in as the first argument, the overlay service creates a new instance of that component and dynamically attaches its ElementRef to the overlay DOM. If moduleRef is provided the service will use the module's ComponentFactoryResolver and Injector when creating the ComponentRef instead of the root ones.
    • An ElementRef to an existing DOM element (illustrated in the sample above) - Any view that is already rendered on the page can be passed through the overlay service and be rendered in the overlay DOM.

    In both cases the attach() method will:

    • Get the reference to the passed view from Angular
    • Detach the view from the DOM and leave an anchor in its place
    • Re-attach the view to the overlay using the provided OverlaySettings or falling back to the default overlay ones

    Calling then show(id) will play the open animation, if there is any, and will show the attached content. Calling hide(id) will play close animation, if there is any, and will hide the attached content.

    Finally calling detach(id) method will re-attach the view back to its original location in the DOM. If a component was provided to the attach() method calling detach(id) will destroy the created instance.

    Attaching Components

    In the below demo, we can pass the IgxCard component through the Overlay Service's attach() method to generate an ID. Then we call the show() method with the provided ID to dynamically attach the card to the DOM in a modal container.

    Overlay Settings

    The attach() method also accepts an object of the OverlaySettings type, which configures the way the content is shown. If no such object is provided, the Overlay Service will use its default settings to render the passed content.

    For example, if we want the content to be positioned relative to an element, we can pass a different target and positioningStrategy to the attach() method, e.g. ConnectedPositioningStrategy. In order to configure how the component is shown, we need to create an OverlaySettings object first:

    // my-overlay-component.component.ts
    // import the ConnectedPositioningStategy class
    import { ConnectedPositioningStrategy } from 'igniteui-angular';
    ...
    export class MyOverlayComponent {
    
        @ViewChild(`myAnchorButton`)
        private myAnchorButton: ElementRef;
        private _overlayId = ''; // The unique identifier assigned to the component by the Overlay service
    
        public showInOverlay() {
            if (!this._overlayId) {
                this._overlayId = this.overlayService.attach(MyDynamicComponent, {
                    target: this.myAnchorButton.nativeElement,
                    positionStrategy: new ConnectedPositioningStrategy()
                });
            }
            this.overlayService.show(this._overlayId);
        }
    }
    
    <!-- my-overlay-component.component.html -->
    <div class='content'>
    ...
    <button #myAnchorButton (click)="showInOverlay()">Show Overlay</button>
    </div>
    

    Clicking on the button will now show MyDynamicComponent positioned relative to the button.

    Preset Overlay Settings

    The IgxOverlayService.createAbsolutePositionSettings() and IgxOverlayService.createRelativePositionSettings() methods provide an easy way to create an OverlaySettings based on a predefined settings sets.

    The IgxOverlayService.createAbsolutePositionSettings() method creates non-modal OverlaySettings with GlobalPositionStrategy or ContainerPositionStrategy in case the outlet parameter is provided. The AbsolutePosition enumeration defines the possible positions to choose from: Center, Top or Bottom. The default position is Center.

    const globalOverlaySettings = IgxOverlayService.createAbsoluteOverlaySettings(AbsolutePosition.Top);
    

    The IgxOverlayService.createRelativePositionSettings() method creates OverlaySettings with AutoPositionStrategy, ConnectedPositioningStrategy or ElasticPositionStrategy. Accepts target, position and strategy. The target is the attaching point or element for the component to show. The position is a RelativePosition enumeration with the following options: Above, Below, Before, After and Default. The Default option positions the element below the target, left aligned. The position strategy can be set through the RelativePositionStrategy enumeration, which default value is Auto.

    const targetElement = this.myAnchorButton.nativeElement;
    const connectedOverlaySettings = IgxOverlayService.createRelativeOverlaySettings(
            targetElement,
            RelativePosition.Above,
            RelativePositionStrategy.Connected);
    

    Demo

    Hiding the Overlay

    The hide(id) hides the overlay content. All of the elements rendered by the overlay service have a unique ID, assigned to them by the service. The attach() method returns the identifier of the rendered content. To hide the content this ID needs to be passed to the overlay's hide(id) method. To hide all overlays hideAll() method could be called.

    When rendered content is not needed anymore detach(id) method should be called. This method removes the content from the overlay and, if applicable, re-attaches it to its original location in the DOM. detach(id) method also accepts as mandatory parameter the ID generated from attach() method. To remove all the overlays detachAll() method could be called.

    We can modify the previously defined overlay method to not only show but also hide the overlay element

    // my-overlay-component.component.ts
    // add an import for the definion of ConnectedPositioningStategy class
    import { ConnectedPositioningStrategy } from 'igniteui-angular';
    ...
    export class MyOverlayComponent implements OnDestroy {
        private _overlayId = ''; // The unique identifier assigned to the component by the Overlay service
        private _overlayShown = false; // Is the component rendered in the Overlay?
    
        @ViewChild(`myAnchorButton`)
        private myAnchorButton: ElementRef;
    
        public toggleOverlay() {
            if (!this._overlayShown) { // If the element is not visible, show it
                //  generate ID
                if (!this._overlayId) {
                    this._overlayId = this.overlayService.attach(MyDynamicComponent, {
                        target: this.myAnchorButton.nativeElement,
                        positionStrategy: new ConnectedPositioningStrategy({
                            closeOnOutsideClick: false, // overlay will not close on outside clicks
                            modal: false // overlay content will not be rendered in a modal dialog
                        }) // The attach method returns an ID that can be used to reference the shown content
                    });
                }
    
                this.overlayService.show(this._overlayId);
            } else {
                this.overlayService.hide(this._overlayId); // If element if visible, hide it
            }
            this._overlayShown = !this._overlayShown;
        }
    
        // finally detach overlay content
        public ngOnDestroy(): void {
            if (this._overlayId) {
                this.overlayService.detach(this._overlayId);
                delete this._overlayId;
            }
        }
    }
    
    <!-- my-overlay-component.component.html -->
    <div class='content'>
    ...
        <button #myAnchorButton (click)="toggleOverlay()">Toggle Overlay</button>
    </div>
    

    Attaching Settings

    Using the overlaySettings parameter of the attach() method, we can change how the content is shown - e.g. where the content is positioned, how the scroll should behave and if the container is modal or not

    If no overlaySettings are configured, the toggled element gets the default display settings:

    defaultOverlaySettings = {
        positionStrategy: new GlobalPositionStrategy(),
        scrollStrategy: new NoOpScrollStrategy(),
        modal: true,
        closeOnOutsideClick: true,
        closeOnEscape: false
    };
    

    Integration with igxToggle

    The IgxToggleDirective is fully integrated with the IgxOverlayService. As such, the Toggle Directive's toggle() method allows for custom overlay settings to be passed when toggling the content.

    An example of how to pass configuration settings to the toggle's method is shown below:

    <!-- In example.component.html -->
    <div>
        <button igxToggle (click)="callToggle()">Click me!</button>
        <div [style.visibility]="collapsed ? 'hidden ' : 'visible'">
            This content is toggle-able!
        </div>
    </div>
    
    // example.component.ts
    @Component({
        selector: `example-component`,
        template: `example.component.html`
    })
    export class ExampleComponent {
        @ViewChild(IgxToggleDirective)
        private toggleDirective: IgxToggleDirective;
    
        public get collapsed(): boolean {
            return this.toggleDirective.collapsed;
        }
    
        public callToggle(): void {
            const overlaySettings: OverlaySettings = {
                positionStrategy: new AutoPositionStrategy(),
                scrollStrategy: new BlockScrollStrategy(),
                modal: true,
                closeOnOutsideClick: false
            }
            this.toggleDirective.toggle(overlaySettings)
        }
    }
    

    Assumptions and Limitations

    If you show the overlay in an outlet, and if the outlet is a child of an element with transform, perspective or filter set in the CSS you won't be able to show the modal overlay. The reason for this is if one of the above mentioned CSS properties is set, the browser creates a new containing block and the overlay is limited to this containing block, as described here.

    API References

    Additional Resources