Components: cdk(feature): Provide custom overlay container

Created on 27 Sep 2017  路  8Comments  路  Source: angular/components

Bug, feature request, or proposal:

[x] Feature request

What is the expected behavior?

In certain scenarios the overlay container has to be positioned somewhere else than as last element of document.body.
The developer should be able to provide a NativeElement (HTMLElement) to CDK referencing a container to be used as overlay container.

What is the current behavior?

Overlay container is appended as last element to document.body

What is the use-case or motivation for changing an existing behavior?

In my case I have a themeing component, inside which all the material styling is applied but the overlay isn't matched as it is positioned outside.
Only applying the class to the container isn't enough as it has to be a child of <my-theme>.

<my-app>
    <my-theme class="myAngularMaterialTheme">
        <!-- all components here get styled correctly //-->
    </my-theme>
</my-app>
<div class="cdk-overlay-container"></div>

Currently I'm hacking it by changing it's position inside MyThemeComponent:

@Component({})
export class MyThemeComponent {
    constructor(elementReference: ElementRef, overlayContainer: OverlayContainer) {
        if(overlayContainer.getContainerElement()) {
            setTimeout(() => elementReference.nativeElement.appendChild(overlayContainer.getContainerElement()), 0);
        }
    }
}
P4 feature

Most helpful comment

I'm having the exact same issue. cdk-overlay-container is causing the options in md-select to appear outside the body.

All 8 comments

Based on the language here, you should be able to provide custom overlay containers. I haven't investigated, so I don't know how flexible that is.

I had seen that and tried to implement it in my module but it didn't seem to work, I'll check that again the next days.

I'm having the exact same issue. cdk-overlay-container is causing the options in md-select to appear outside the body.

@actra-gschuster see this example (from a similar issue) for providing a different overlay container

https://stackblitz.com/edit/angular-material2-issue-ansnt5?file=app%2Fapp.module.ts

Thanks for the demo!
I now managed it to use an element declared in the template as OverlayContainer by "reading" it with a directive that sets the reference on a "service" class that is used / provided as my custom OverlayContainer.
In the template there's simply a DIV that's matched by the directive, so I can position it wherever it needs to be, now styling works as expected.

Problem solved, issue closed - thanks again!

import { OverlayContainer } from '@angular/cdk/overlay';
export class CdkOverlayContainer extends OverlayContainer {
    /**
     * Set the container element from the outside, e.g. from the corresponding directive
     */
    public setContainerElement(element: HTMLElement): void {
        this._containerElement = element;
    }
    /**
     * Prevent creation of the HTML element
     */
    protected _createContainer(): void {
        return;
    }
}
import {
    Directive,
    ElementRef,
    Renderer2
} from '@angular/core';
import { CdkOverlayContainer } from './cdk-overlay-container';

@Directive({
    selector: '[myCdkOverlayContainer]'
})
export class CdkOverlayContainerDirective {
    protected renderer: Renderer2;
    protected elementReference: ElementRef;
    protected cdkOverlayContainer: CdkOverlayContainer;
    constructor(renderer: Renderer2, elementReference: ElementRef, cdkOverlayContainer: CdkOverlayContainer) {
        this.renderer            = renderer;
        this.elementReference    = elementReference;
        this.cdkOverlayContainer = cdkOverlayContainer;

        this.renderer.addClass(this.elementReference.nativeElement, 'cdk-overlay-container');
        this.cdkOverlayContainer.setContainerElement(this.elementReference.nativeElement);
    }
}

@actra-gschuster any chance you could provide a bit more detail? I'm struggling to fully implement your approach yet it seems exactly what I need. Anyway thanks a lot for your idea.

Where exactly are you struggeling?
Despite a "{provide: OverlayContainer,...}" there shouldn't be more code than shown above.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

julianobrasil picture julianobrasil  路  3Comments

Miiekeee picture Miiekeee  路  3Comments

kara picture kara  路  3Comments

shlomiassaf picture shlomiassaf  路  3Comments

alanpurple picture alanpurple  路  3Comments