Skip to content

Commit 262b2f2

Browse files
authored
Merge pull request #223 from cal-smith/appendto
fix: change everything to append to the body by default
2 parents 5a2a3e1 + 6906d5f commit 262b2f2

File tree

11 files changed

+68
-144
lines changed

11 files changed

+68
-144
lines changed

.storybook/preview.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@import "~carbon-components/css/carbon-components.min.css";
22

33
body {
4-
margin: 20px;
4+
padding: 20px;
55
// for tooltips/popovers ... can be on any chld element before the popover
66
// but body is most conveient
77
position: relative;

src/dialog/dialog-config.interface.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,37 @@ import { ElementRef, TemplateRef } from "@angular/core";
88
export interface DialogConfig {
99
/**
1010
* Title for the `Dialog` header.
11-
* @type {string}
12-
* @memberof DialogConfig
1311
*/
1412
title: string;
1513
/**
1614
* Body content for the `Dialog`.
17-
* @type {(string | TemplateRef<any>)}
18-
* @memberof DialogConfig
1915
*/
2016
content: string | TemplateRef<any>;
2117
/**
2218
* Parameter for triggering `Dialog` display.
2319
* With the release of v2.0 the type will just be "click" or "hover".
24-
* @type {("click" | "hover" | "mouseenter")}
25-
* @memberof DialogConfig
2620
*/
2721
trigger: "click" | "hover" | "mouseenter";
2822
/**
2923
* Parameter defining the placement in which the `Dialog` appears.
3024
* @type {Placement}
31-
* @memberof DialogConfig
3225
*/
3326
placement: string;
3427
/**
3528
* Used to set the offset of the `Dialog` relative to the content it
3629
* is associated to.
37-
* @type {number}
38-
* @memberof DialogConfig
3930
*/
4031
gap: number;
4132
/**
4233
* Reference to the Parent element that links the `Dialog`.
43-
* @type {ElementRef}
44-
* @memberof DialogConfig
4534
*/
4635
parentRef: ElementRef;
4736
/**
48-
* Set to `true` will append `Dialog` to body causing
49-
* it to break out of containers.
50-
* @type {boolean}
51-
* @memberof DialogConfig
37+
* Set to `true` to open the dialog next to the triggering component
5238
*/
53-
appendToBody: boolean;
54-
/**
55-
* Set to `true` will attempt to place
56-
* `Dialog` for maximum visibility.
57-
* TODO: remove - this doesn't actually do anything
58-
* @type {boolean | string}
59-
* @memberof DialogConfig
60-
* @deprecated
61-
*/
62-
autoPosition: boolean;
39+
appendInline: boolean;
6340
/**
6441
* Config object passed to the rendered component. (Optional)
65-
* @type {Object}
66-
* @memberof DialogConfig
6742
*/
6843
data: Object;
6944
[propName: string]: any;

src/dialog/dialog.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
166166

167167
const placeDialogInContainer = () => {
168168
// only do the work to find the scroll containers if we're appended to body
169-
if (this.dialogConfig.appendToBody) {
169+
// or skip this work if we're inline
170+
if (!this.dialogConfig.appendInline) {
170171
// walk the parents and subscribe to all the scroll events we can
171172
while (node.parentElement && node !== document.body) {
172173
if (isScrollableElement(node)) {
@@ -203,11 +204,11 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
203204
// helper to find the position based on the current/given environment
204205
const findPosition = (reference, target, placement) => {
205206
let pos;
206-
if (this.dialogConfig.appendToBody) {
207+
if (this.dialogConfig.appendInline) {
208+
pos = this.addGap[placement](position.findRelative(reference, target, placement));
209+
} else {
207210
pos = this.addGap[placement](position.findAbsolute(reference, target, placement));
208211
pos = position.addOffset(pos, window.scrollY, window.scrollX);
209-
} else {
210-
pos = this.addGap[placement](position.findRelative(reference, target, placement));
211212
}
212213
return pos;
213214
};

src/dialog/dialog.directive.ts

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,61 +36,55 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
3636
/**
3737
* Title for the dialog
3838
* @type {string}
39-
* @memberof DialogDirective
4039
*/
4140
@Input() title = "";
4241
/**
4342
* Dialog body content.
4443
* @type {(string | TemplateRef<any>)}
45-
* @memberof DialogDirective
4644
*/
4745
@Input() ibmDialog: string | TemplateRef<any>;
4846
/**
4947
* Defines how the Dialog is triggered.(Hover and click behave the same on mobile - both respond to a single tap)
5048
* @type {("click" | "hover" | "mouseenter")}
51-
* @memberof DialogDirective
5249
*/
5350
@Input() trigger: "click" | "hover" | "mouseenter" = "click";
5451
/**
5552
* Placement of the dialog, usually relative to the element the directive is on.
56-
* @memberof DialogDirective
5753
*/
5854
@Input() placement = "left";
5955
/**
6056
* Class to add to the dialog container
6157
* @type {string}
62-
* @memberof DialogDirective
6358
*/
6459
@Input() wrapperClass: string;
6560
/**
6661
* Spacing between the dialog and it's triggering element
6762
* @type {number}
68-
* @memberof DialogDirective
6963
*/
7064
@Input() gap = 0;
7165
/**
66+
* Deprecated. Defaults to true. Use appendInline to keep dialogs within page flow
7267
* Value `true` sets Dialog be appened to the body (to break out of containers)
73-
* @type {boolean}
74-
* @memberof DialogDirective
7568
*/
76-
@Input() appendToBody = false;
69+
@Input() set appendToBody(v: boolean) {
70+
console.log("`appendToBody` has been deprecated. Dialogs now append to the body by default.");
71+
console.log("Ensure you have an `ibm-placeholder` in your app.");
72+
console.log("Use `appendInline` if you need to position your dialogs within the normal page flow.");
73+
this.appendInline = !v;
74+
}
75+
get appendToBody() {
76+
return !this.appendInline;
77+
}
7778
/**
78-
* Determines if the Dialog will attempt to place itself for maximum visibility.
79-
* TODO: remove - this doesn't actually do anything
80-
* @type {boolean}
81-
* @memberof DialogDirective
82-
* @deprecated
79+
* Set to `true` to open the dialog next to the triggering component
8380
*/
84-
@Input() autoPosition: boolean;
81+
@Input() appendInline = false;
8582
/**
8683
* Optional data for templates
87-
* @memberof DialogDirective
8884
*/
8985
@Input() data = {};
9086
/**
9187
* Config object passed to the rendered component
92-
* @type {DialogConfig}
93-
* @memberof DialogDirective
9488
*/
9589
@Output() onClose: EventEmitter<any> = new EventEmitter<any>();
9690
dialogConfig: DialogConfig;
@@ -103,7 +97,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
10397
* @param {ElementRef} elementRef
10498
* @param {ViewContainerRef} viewContainerRef
10599
* @param {DialogService} dialogService
106-
* @memberof DialogDirective
107100
*/
108101
constructor(
109102
protected elementRef: ElementRef,
@@ -113,7 +106,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
113106
/**
114107
* Overrides 'touchstart' event to trigger a toggle on the Dialog.
115108
* @param {any} evt
116-
* @memberof DialogDirective
117109
*/
118110
@HostListener("touchstart", ["$event"])
119111
onTouchStart(evt) {
@@ -131,8 +123,7 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
131123
parentRef: this.elementRef,
132124
gap: this.gap,
133125
trigger: this.trigger,
134-
appendToBody: this.appendToBody,
135-
autoPosition: this.autoPosition,
126+
appendInline: this.appendInline,
136127
wrapperClass: this.wrapperClass,
137128
data: this.data
138129
};
@@ -141,7 +132,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
141132
/**
142133
* Sets the config object and binds events for hovering or clicking before
143134
* running code from child class.
144-
* @memberof DialogDirective
145135
*/
146136
ngOnInit() {
147137
// fix for safari hijacking clicks
@@ -173,7 +163,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
173163
/**
174164
* When the host dies, kill the popover.
175165
* - Useful for use in a modal or similar.
176-
* @memberof DialogDirective
177166
*/
178167
ngOnDestroy() {
179168
this.close();
@@ -182,7 +171,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
182171
/**
183172
* Helper method to call dialogService 'open'.
184173
* - Enforce accessibility by updating an aria attr for nativeElement.
185-
* @memberof DialogDirective
186174
*/
187175
open() {
188176
this.dialogService.open(this.viewContainerRef, this.dialogConfig);
@@ -192,7 +180,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
192180
/**
193181
* Helper method to call dialogService 'toggle'.
194182
* - Enforce accessibility by updating an aria attr for nativeElement.
195-
* @memberof DialogDirective
196183
*/
197184
toggle() {
198185
this.dialogService.toggle(this.viewContainerRef, this.dialogConfig);
@@ -202,7 +189,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
202189
/**
203190
* Helper method to call dialogService 'close'.
204191
* - Enforce accessibility by updating an aria attr for nativeElement.
205-
* @memberof DialogDirective
206192
*/
207193
close() {
208194
this.dialogService.close(this.viewContainerRef);
@@ -213,7 +199,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
213199
* Empty method for child classes to override and specify additional init steps.
214200
* Run after DialogDirective completes it's ngOnInit.
215201
* @protected
216-
* @memberof DialogDirective
217202
*/
218203
protected onDialogInit() {}
219204
}

src/dialog/dialog.service.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,16 @@ export class DialogService {
103103
*/
104104
open(viewContainer: ViewContainerRef, dialogConfig: DialogConfig) {
105105
if (!this.dialogRef) {
106-
// holder for either the provided view, or the view from Placeholder
107-
if (dialogConfig.appendToBody) {
108-
// add our component to the placeholder
109-
this.dialogRef = this.placeholderService.createComponent(this.componentFactory, this.injector);
110-
} else {
106+
if (dialogConfig.appendInline) {
111107
// add our component to the view
112108
this.dialogRef = viewContainer.createComponent(this.componentFactory, 0, this.injector);
109+
} else if (!this.placeholderService.hasPlaceholderRef()) {
110+
this.dialogRef = viewContainer.createComponent(this.componentFactory, 0, this.injector);
111+
setTimeout(() => {
112+
window.document.querySelector("body").appendChild(this.dialogRef.location.nativeElement);
113+
});
114+
} else {
115+
this.dialogRef = this.placeholderService.createComponent(this.componentFactory, this.injector);
113116
}
114117

115118
// initialize some extra options
@@ -140,7 +143,7 @@ export class DialogService {
140143

141144
if (this.dialogRef) {
142145
let elementToFocus = this.dialogRef.instance.dialogConfig["previouslyFocusedElement"];
143-
if (this.dialogRef.instance.dialogConfig.appendToBody) {
146+
if (this.placeholderService.hasPlaceholderRef() && !this.dialogRef.instance.dialogConfig.appendInline) {
144147
this.placeholderService.destroyComponent(this.dialogRef);
145148
} else {
146149
viewContainer.remove(viewContainer.indexOf(this.dialogRef.hostView));

src/dialog/overflow-menu/overflow-menu.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { I18n } from "./../../i18n/i18n.module";
1717
template: `
1818
<div
1919
[ibmOverflowMenu]="options"
20-
[appendToBody]="true"
2120
[ngClass]="{'bx--overflow-menu--open': open === true}"
2221
[attr.aria-label]="buttonLabel"
2322
class="bx--overflow-menu"

src/dialog/tooltip/tooltip.directive.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ describe("Tooltip directive", () => {
3939
it("should create the tooltip component and tooltip should appear at the top", () => {
4040
TestBed.overrideComponent(TooltipTest, {
4141
set: {
42-
template: "<button ibmTooltip='Hello There' placement='top'>Me</button>"
42+
template: `
43+
<button ibmTooltip="Hello There" placement="top">Me</button>
44+
<ibm-placeholder></ibm-placeholder>
45+
`
4346
}
4447
});
4548
const fixture = TestBed.createComponent(TooltipTest);

0 commit comments

Comments
 (0)