src/dialog/dialog.directive.ts
A generic directive that can be inherited from to create dialogs (for example, a tooltip or popover)
This class contains the relevant intilization code, specific templates, options, and additional inputs should be specified in the derived class.
NOTE: All child classes should add DialogService as a provider, otherwise they will lose context that
the service relies on.
| providers |
DialogService
|
| selector | [ibmDialog] |
Properties |
Methods |
|
Inputs |
Outputs |
HostBindings |
HostListeners |
Accessors |
constructor(elementRef: ElementRef, viewContainerRef: ViewContainerRef, dialogService: DialogService)
|
||||||||||||||||
|
Defined in src/dialog/dialog.directive.ts:93
|
||||||||||||||||
|
Creates an instance of DialogDirective.
Parameters :
|
appendInline
|
Set to
Default value: |
|
Defined in src/dialog/dialog.directive.ts:81
|
|
appendToBody
|
Deprecated. Defaults to true. Use appendInline to keep dialogs within page flow
Value
Type: |
|
Defined in src/dialog/dialog.directive.ts:69
|
|
data
|
Optional data for templates |
|
Defined in src/dialog/dialog.directive.ts:85
|
|
gap
|
Spacing between the dialog and it's triggering element
Default value: |
|
Defined in src/dialog/dialog.directive.ts:64
|
|
ibmDialog
|
Dialog body content.
Type: |
|
Defined in src/dialog/dialog.directive.ts:45
|
|
placement
|
Placement of the dialog, usually relative to the element the directive is on.
Default value: |
|
Defined in src/dialog/dialog.directive.ts:54
|
|
title
|
Title for the dialog |
|
Defined in src/dialog/dialog.directive.ts:40
|
|
trigger
|
Defines how the Dialog is triggered.(Hover and click behave the same on mobile - both respond to a single tap)
Type:
Default value: |
|
Defined in src/dialog/dialog.directive.ts:50
|
|
wrapperClass
|
Class to add to the dialog container
Type: |
|
Defined in src/dialog/dialog.directive.ts:59
|
|
onClose
|
Config object passed to the rendered component $event type: EventEmitter<any>
|
|
Defined in src/dialog/dialog.directive.ts:89
|
|
| attr.aria-expanded |
attr.aria-expanded:
|
Default value : false
|
|
Defined in src/dialog/dialog.directive.ts:93
|
| attr.role |
attr.role:
|
Default value : button
|
|
Defined in src/dialog/dialog.directive.ts:92
|
| touchstart |
Arguments : '$event'
|
touchstart(evt: )
|
|
Defined in src/dialog/dialog.directive.ts:111
|
| close |
close()
|
|
Defined in src/dialog/dialog.directive.ts:193
|
|
Helper method to call dialogService 'close'.
Returns :
void
|
| ngOnChanges |
ngOnChanges()
|
|
Defined in src/dialog/dialog.directive.ts:117
|
|
Returns :
void
|
| ngOnDestroy |
ngOnDestroy()
|
|
Defined in src/dialog/dialog.directive.ts:167
|
|
When the host dies, kill the popover.
Returns :
void
|
| ngOnInit |
ngOnInit()
|
|
Defined in src/dialog/dialog.directive.ts:136
|
|
Sets the config object and binds events for hovering or clicking before running code from child class.
Returns :
void
|
| Protected onDialogInit |
onDialogInit()
|
|
Defined in src/dialog/dialog.directive.ts:203
|
|
Empty method for child classes to override and specify additional init steps. Run after DialogDirective completes it's ngOnInit.
Returns :
void
|
| open |
open()
|
|
Defined in src/dialog/dialog.directive.ts:175
|
|
Helper method to call dialogService 'open'.
Returns :
void
|
| toggle |
toggle()
|
|
Defined in src/dialog/dialog.directive.ts:184
|
|
Helper method to call dialogService 'toggle'.
Returns :
void
|
| dialogConfig |
dialogConfig:
|
Type : DialogConfig
|
|
Defined in src/dialog/dialog.directive.ts:90
|
| appendToBody | ||||||||
getappendToBody()
|
||||||||
|
Defined in src/dialog/dialog.directive.ts:75
|
||||||||
setappendToBody(v: boolean)
|
||||||||
|
Defined in src/dialog/dialog.directive.ts:69
|
||||||||
|
Deprecated. Defaults to true. Use appendInline to keep dialogs within page flow
Value
Parameters :
Returns :
void
|
import {
Directive,
Input,
Output,
EventEmitter,
OnInit,
OnDestroy,
ElementRef,
TemplateRef,
ViewContainerRef,
HostListener,
OnChanges,
HostBinding
} from "@angular/core";
import { fromEvent } from "rxjs";
import { DialogService } from "./dialog.service";
import { DialogConfig } from "./dialog-config.interface";
/**
* A generic directive that can be inherited from to create dialogs (for example, a tooltip or popover)
*
* This class contains the relevant intilization code, specific templates, options, and additional inputs
* should be specified in the derived class.
*
* NOTE: All child classes should add `DialogService` as a provider, otherwise they will lose context that
* the service relies on.
*/
@Directive({
selector: "[ibmDialog]",
exportAs: "ibmDialog",
providers: [
DialogService
]
})
export class DialogDirective implements OnInit, OnDestroy, OnChanges {
/**
* Title for the dialog
* @type {string}
*/
@Input() title = "";
/**
* Dialog body content.
* @type {(string | TemplateRef<any>)}
*/
@Input() ibmDialog: string | TemplateRef<any>;
/**
* Defines how the Dialog is triggered.(Hover and click behave the same on mobile - both respond to a single tap)
* @type {("click" | "hover" | "mouseenter")}
*/
@Input() trigger: "click" | "hover" | "mouseenter" = "click";
/**
* Placement of the dialog, usually relative to the element the directive is on.
*/
@Input() placement = "left";
/**
* Class to add to the dialog container
* @type {string}
*/
@Input() wrapperClass: string;
/**
* Spacing between the dialog and it's triggering element
* @type {number}
*/
@Input() gap = 0;
/**
* Deprecated. Defaults to true. Use appendInline to keep dialogs within page flow
* Value `true` sets Dialog be appened to the body (to break out of containers)
*/
@Input() set appendToBody(v: boolean) {
console.log("`appendToBody` has been deprecated. Dialogs now append to the body by default.");
console.log("Ensure you have an `ibm-placeholder` in your app.");
console.log("Use `appendInline` if you need to position your dialogs within the normal page flow.");
this.appendInline = !v;
}
get appendToBody() {
return !this.appendInline;
}
/**
* Set to `true` to open the dialog next to the triggering component
*/
@Input() appendInline = false;
/**
* Optional data for templates
*/
@Input() data = {};
/**
* Config object passed to the rendered component
*/
@Output() onClose: EventEmitter<any> = new EventEmitter<any>();
dialogConfig: DialogConfig;
@HostBinding("attr.role") role = "button";
@HostBinding("attr.aria-expanded") expanded = false;
/**
* Creates an instance of DialogDirective.
* @param {ElementRef} elementRef
* @param {ViewContainerRef} viewContainerRef
* @param {DialogService} dialogService
*/
constructor(
protected elementRef: ElementRef,
protected viewContainerRef: ViewContainerRef,
protected dialogService: DialogService) {}
/**
* Overrides 'touchstart' event to trigger a toggle on the Dialog.
* @param {any} evt
*/
@HostListener("touchstart", ["$event"])
onTouchStart(evt) {
evt.stopImmediatePropagation();
evt.preventDefault();
this.toggle();
}
ngOnChanges() {
// set the config object (this can [and should!] be added to in child classes depending on what they need)
this.dialogConfig = {
title: this.title,
content: this.ibmDialog,
placement: this.placement,
parentRef: this.elementRef,
gap: this.gap,
trigger: this.trigger,
appendInline: this.appendInline,
wrapperClass: this.wrapperClass,
data: this.data
};
}
/**
* Sets the config object and binds events for hovering or clicking before
* running code from child class.
*/
ngOnInit() {
// fix for safari hijacking clicks
this.dialogService.singletonClickListen();
// bind events for hovering or clicking the host
if (this.trigger === "hover" || this.trigger === "mouseenter") {
fromEvent(this.elementRef.nativeElement, "mouseenter").subscribe(() => this.toggle());
fromEvent(this.elementRef.nativeElement, "mouseout").subscribe(() => this.close());
fromEvent(this.elementRef.nativeElement, "focus").subscribe(() => this.open());
fromEvent(this.elementRef.nativeElement, "blur").subscribe(() => this.close());
} else {
fromEvent(this.elementRef.nativeElement, "click").subscribe(() => this.toggle());
}
// call onClose when the dialog is closed
// - Enforce accessibility by updating an aria attr for nativeElement.
this.dialogService.isClosed.subscribe(value => {
if (value) {
this.onClose.emit();
this.expanded = false;
}
});
// run any code a child class may need
this.onDialogInit();
}
/**
* When the host dies, kill the popover.
* - Useful for use in a modal or similar.
*/
ngOnDestroy() {
this.close();
}
/**
* Helper method to call dialogService 'open'.
* - Enforce accessibility by updating an aria attr for nativeElement.
*/
open() {
this.dialogService.open(this.viewContainerRef, this.dialogConfig);
this.expanded = true;
}
/**
* Helper method to call dialogService 'toggle'.
* - Enforce accessibility by updating an aria attr for nativeElement.
*/
toggle() {
this.dialogService.toggle(this.viewContainerRef, this.dialogConfig);
this.expanded = this.dialogService.isOpen;
}
/**
* Helper method to call dialogService 'close'.
* - Enforce accessibility by updating an aria attr for nativeElement.
*/
close() {
this.dialogService.close(this.viewContainerRef);
this.expanded = false;
}
/**
* Empty method for child classes to override and specify additional init steps.
* Run after DialogDirective completes it's ngOnInit.
* @protected
*/
protected onDialogInit() {}
}