Recobrir
O serviço de sobreposição fornece uma maneira fácil e rápida de renderizar dinamicamente o conteúdo no primeiro plano de um aplicativo. O conteúdo a ser renderizado, também a maneira como ele renderiza (por exemplo, posicionamento, animações, comportamentos de rolagem e clique) são altamente configuráveis e capazes de corresponder a todos os cenários possíveis. O serviço de sobreposição é totalmente integrado na diretiva toggle.
Angular Overlay Example
Getting Started
Primeiro precisamos importar o IgxOverlayService
no componente e inject
uma referência a ele no construtor do componente:
import { Inject } from '@angular/core'
import { IgxOverlayService } from `igniteui-angular`;
...
export class MyOverlayComponent {
constructor(
@Inject(IgxOverlayService) private overlayService: IgxOverlayService
) {}
}
...
Displaying Content
O serviço de sobreposição pode ser usado para exibir dinamicamente um HTMLNode
ou até mesmo um componente Angular anexando-o ao DOM de sobreposição.
Após uma referência ao serviço Overlay ser estabelecida, ela pode ser usada para mostrar/ocultar conteúdo dinamicamente. Por exemplo, podemos passar um Angular Component no método attach
. Isso gerará um ID exclusivo, que podemos passar para o método show
para exibir o componente. Ao exibir um Angular Component, um segundo parâmetro obrigatório ViewContainerRef
deve ser passado no método attach
.
// my-overlay-component.component.ts
import { MyDynamicComponent } from '../my-dynamic-component/my-dynamic-component.component';
@Component({...})
export class MyOverlayComponent {
private _overlayId = ''; // The unique identifier assigned to the component by the Overlay service
constructor(
@Inject(IgxOverlayService) private overlayService: IgxOverlayService,
private viewContainerRef: ViewContainerRef
) {}
public showInOverlay() {
if (!this._overlayId) {
this._overlayId = this.overlayService.attach(MyDynamicComponent, this.viewContainerRef);
}
this.overlayService.show(this._overlayId);
}
}
<!-- my-overlay-component.component.html -->
<div class='content'>
...
<button (click)="showInOverlay()">Show Overlay</button>
</div>
Se quisermos passar um ElementRef
já existente da página para o IgxOverlayService
, podemos fazer isso da seguinte maneira:
<!-- 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'
@Component({...})
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);
}
}
O método attach()
do Overlay Service tem duas sobrecargas:
attach(element, settings?)
attach(component, viewContainerRef, settings?)
O primeiro parâmetro em ambas as sobrecargas é obrigatório e representa o conteúdo que será mostrado na sobreposição. Há alguns cenários diferentes de como o conteúdo pode ser passado:
- Uma definição de componente - Ao passar um componente como o primeiro argumento, o serviço de sobreposição cria uma nova instância desse componente e anexa dinamicamente seu
ElementRef
ao DOMoverlay
. Esse método também aceita um segundo parâmetro obrigatórioViewContainerRef
que é uma referência ao contêiner onde a visualização do host do componente criado será inserida. - Um
ElementRef
para um elemento DOM existente (ilustrado no exemplo acima) - Qualquer visualização que já esteja renderizada na página pode ser passada pelo serviço de sobreposição e renderizada no DOM de sobreposição.
Em ambos os casos, o método attach()
irá:
- Obter a referência para a visualização passada do Angular
- Desanexe a visualização do DOM e deixe uma âncora em seu lugar
- Reanexe a visualização à sobreposição usando as
OverlaySettings
fornecidas ou retornando às sobreposições padrão
Chamar show(id)
reproduzirá a animação de abertura, se houver, e mostrará o conteúdo anexado. Chamar hide(id)
reproduzirá a animação de fechamento, se houver, e ocultará o conteúdo anexado.
Finalmente, chamar o método detach(id)
irá re-anexar a visualização de volta ao seu local original no DOM. Se um componente foi fornecido ao método attach()
chamar detach(id)
irá destruir a instância criada.
Attaching Components
Na demonstração abaixo, podemos passar o componente IgxCard pelo método attach()
do Overlay Service para gerar um ID. Então, chamamos o método show()
com o ID fornecido para anexar dinamicamente o cartão ao DOM em um contêiner modal.
Overlay Settings
O método attach()
também aceita um objeto do tipo OverlaySettings
, que configura a maneira como o conteúdo é exibido. Se nenhum objeto desse tipo for fornecido, o Overlay Service usará suas configurações padrão para renderizar o conteúdo passado.
Por exemplo, se quisermos que o conteúdo seja posicionado em relação a um elemento, podemos passar um target
e positioningStrategy
diferentes para o método attach()
, por exemplo, ConnectedPositioningStrategy
. Para configurar como o componente é exibido, precisamos criar um objeto OverlaySettings
primeiro:
// my-overlay-component.component.ts
// import the ConnectedPositioningStategy class
import { ConnectedPositioningStrategy } from 'igniteui-angular';
// import { ConnectedPositioningStrategy } from '@infragistics/igniteui-angular'; for licensed package
...
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, this.viewContainerRef, {
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>
Clicar no botão agora mostrará MyDynamicComponent
posicionado em relação ao botão.
Preset Overlay Settings
Os métodos IgxOverlayService.createAbsolutePositionSettings()
e IgxOverlayService.createRelativePositionSettings()
fornecem uma maneira fácil de criar um OverlaySettings
com base em conjuntos de configurações predefinidos.
O método IgxOverlayService.createAbsolutePositionSettings()
cria OverlaySettings
não modais com GlobalPositionStrategy
ou ContainerPositionStrategy
caso o parâmetro outlet
seja fornecido. A enumeração AbsolutePosition
define as posições possíveis para escolher: Center
, Top
ou Bottom
. A posição padrão é Center
.
const globalOverlaySettings = IgxOverlayService.createAbsoluteOverlaySettings(AbsolutePosition.Top);
O método IgxOverlayService.createRelativePositionSettings()
cria OverlaySettings
com AutoPositionStrategy
, ConnectedPositioningStrategy
ou ElasticPositionStrategy
. Aceita target, position e strategy. O target
é o ponto de anexação ou elemento para o componente mostrar. A position
é uma enumeração RelativePosition
com as seguintes opções: Above
, Below
, Before
, After
e Default
. A opção Default
posiciona o elemento abaixo do target, alinhado à esquerda. A estratégia de posição pode ser definida por meio da enumeração RelativePositionStrategy
, cujo valor padrão é Auto
.
const targetElement = this.myAnchorButton.nativeElement;
const connectedOverlaySettings = IgxOverlayService.createRelativeOverlaySettings(
targetElement,
RelativePosition.Above,
RelativePositionStrategy.Connected);
Demo
Hiding the Overlay
O hide(id)
oculta o conteúdo da sobreposição. Todos os elementos renderizados pelo serviço de sobreposição têm um ID exclusivo, atribuído a eles pelo serviço. O método attach()
retorna o identificador do conteúdo renderizado. Para ocultar o conteúdo, esse ID precisa ser passado para o método hide(id)
da sobreposição. Para ocultar todas as sobreposições, o método hideAll()
pode ser chamado.
Quando o conteúdo renderizado não for mais necessário, o método detach(id)
deve ser chamado. Este método remove o conteúdo da sobreposição e, se aplicável, o reconecta ao seu local original no DOM. O método detach(id)
também aceita como parâmetro obrigatório o ID gerado pelo método attach()
. Para remover todas as sobreposições, o método detachAll()
pode ser chamado.
Podemos modificar o método de sobreposição definido anteriormente para não apenas mostrar, mas também ocultar o elemento de sobreposição
// my-overlay-component.component.ts
// add an import for the definion of ConnectedPositioningStategy class
import { ConnectedPositioningStrategy } from 'igniteui-angular';
// import { ConnectedPositioningStrategy } from '@infragistics/igniteui-angular'; for licensed package
@Component({...})
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, this.viewContainerRef, {
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
Usando o parâmetro overlaySettings
do método attach()
, podemos alterar como o conteúdo é exibido - por exemplo, onde o conteúdo é posicionado, como a rolagem deve se comportar e se o contêiner é modal ou não
Se nenhuma overlaySettings
for configurada, o elemento alternado obterá as configurações de exibição padrão:
defaultOverlaySettings = {
positionStrategy: new GlobalPositionStrategy(),
scrollStrategy: new NoOpScrollStrategy(),
modal: true,
closeOnOutsideClick: true,
closeOnEscape: false
};
Integration with igxToggle
A IgxToggleDirective
é totalmente integrada com a IgxOverlayService
. Como tal, o método toggle()
da Toggle Directive permite que configurações de sobreposição personalizadas sejam passadas ao alternar o conteúdo.
Um exemplo de como passar configurações para o método toggle é mostrado abaixo:
<!-- 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
Se você mostrar a sobreposição em um outlet, e se o outlet for filho de um elemento com transform, perspective ou filter definido no CSS, você não poderá mostrar a sobreposição modal. O motivo para isso é que se uma das propriedades CSS mencionadas acima for definida, o navegador cria um novo bloco de contenção e a sobreposição é limitada a esse bloco de contenção, conforme descrito aqui.