Skip to content

Commit dba3d27

Browse files
authored
Merge branch 'master' into notes
2 parents ad696db + 93f696e commit dba3d27

File tree

5 files changed

+90
-20
lines changed

5 files changed

+90
-20
lines changed

src/dialog/dialog-config.interface.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ export interface DialogConfig {
1414
content: string | TemplateRef<any>;
1515
/**
1616
* Parameter for triggering `Dialog` display.
17-
* With the release of v2.0 the type will just be "click" or "hover".
1817
*/
1918
trigger: "click" | "hover" | "mouseenter";
19+
/**
20+
* Parameter for triggering the `Dialog` close event.
21+
*/
22+
closeTrigger: "mouseout" | "mouseleave";
2023
/**
2124
* Parameter defining the placement in which the `Dialog` appears.
2225
* @type {Placement}

src/dialog/dialog.directive.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,35 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
3636
static dialogCounter = 0;
3737
/**
3838
* Title for the dialog
39-
* @type {string}
4039
*/
4140
@Input() title = "";
4241
/**
4342
* Dialog body content.
44-
* @type {(string | TemplateRef<any>)}
4543
*/
4644
@Input() ibmDialog: string | TemplateRef<any>;
4745
/**
4846
* Defines how the Dialog is triggered.(Hover and click behave the same on mobile - both respond to a single tap)
49-
* @type {("click" | "hover" | "mouseenter")}
5047
*/
5148
@Input() trigger: "click" | "hover" | "mouseenter" = "click";
49+
/**
50+
* Defines how the Dialog close event is triggered.
51+
*
52+
* [See here](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseleave_event)
53+
* for more on the difference between `mouseleave` and `mouseout`.
54+
*
55+
* Defaults to `click` when `trigger` is set to `click`.
56+
*/
57+
@Input() closeTrigger: "mouseout" | "mouseleave" = "mouseleave";
5258
/**
5359
* Placement of the dialog, usually relative to the element the directive is on.
5460
*/
5561
@Input() placement = "left";
5662
/**
5763
* Class to add to the dialog container
58-
* @type {string}
5964
*/
6065
@Input() wrapperClass: string;
6166
/**
6267
* Spacing between the dialog and it's triggering element
63-
* @type {number}
6468
*/
6569
@Input() gap = 0;
6670
/**
@@ -117,7 +121,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
117121

118122
/**
119123
* Overrides 'touchstart' event to trigger a toggle on the Dialog.
120-
* @param {any} evt
121124
*/
122125
@HostListener("touchstart", ["$event"])
123126
onTouchStart(evt) {
@@ -135,6 +138,7 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
135138
parentRef: this.elementRef,
136139
gap: this.gap,
137140
trigger: this.trigger,
141+
closeTrigger: this.closeTrigger,
138142
appendInline: this.appendInline,
139143
wrapperClass: this.wrapperClass,
140144
data: this.data
@@ -160,7 +164,7 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
160164
// bind events for hovering or clicking the host
161165
if (this.trigger === "hover" || this.trigger === "mouseenter") {
162166
fromEvent(this.elementRef.nativeElement, "mouseenter").subscribe(() => this.toggle());
163-
fromEvent(this.elementRef.nativeElement, "mouseout").subscribe(() => this.close());
167+
fromEvent(this.elementRef.nativeElement, this.closeTrigger).subscribe(() => this.close());
164168
fromEvent(this.elementRef.nativeElement, "focus").subscribe(() => this.open());
165169
fromEvent(this.elementRef.nativeElement, "blur").subscribe(() => this.close());
166170
} else {
@@ -231,7 +235,6 @@ export class DialogDirective implements OnInit, OnDestroy, OnChanges {
231235
/**
232236
* Empty method for child classes to override and specify additional init steps.
233237
* Run after DialogDirective completes it's ngOnInit.
234-
* @protected
235238
*/
236239
protected onDialogInit() {}
237240
}

src/dropdown/dropdown.component.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
ViewChild,
1010
AfterContentInit,
1111
HostListener,
12-
OnDestroy
12+
OnDestroy,
13+
TemplateRef
1314
} from "@angular/core";
1415
import { NG_VALUE_ACCESSOR } from "@angular/forms";
1516

@@ -75,7 +76,12 @@ import { DropdownService } from "./dropdown.service";
7576
<path d="M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8z"></path>
7677
</svg>
7778
</div>
78-
<span class="bx--list-box__label">{{getDisplayValue() | async}}</span>
79+
<span *ngIf="isRenderString()" class="bx--list-box__label">{{getDisplayStringValue() | async}}</span>
80+
<ng-template
81+
*ngIf="!isRenderString()"
82+
[ngTemplateOutletContext]="getRenderTemplateContext()"
83+
[ngTemplateOutlet]="displayValue">
84+
</ng-template>
7985
<ibm-icon-chevron-down16
8086
*ngIf="!skeleton"
8187
class="bx--list-box__menu-icon"
@@ -106,9 +112,9 @@ export class Dropdown implements OnInit, AfterContentInit, OnDestroy {
106112
*/
107113
@Input() placeholder = "";
108114
/**
109-
* The selected value from the `Dropdown`.
115+
* The selected value from the `Dropdown`. Can be a string or template.
110116
*/
111-
@Input() displayValue = "";
117+
@Input() displayValue: string | TemplateRef<any> = "";
112118
/**
113119
* Size to render the dropdown field.
114120
*/
@@ -367,23 +373,41 @@ export class Dropdown implements OnInit, AfterContentInit, OnDestroy {
367373
* if there is just a selection the ListItem content property will be returned,
368374
* otherwise the placeholder will be returned.
369375
*/
370-
getDisplayValue(): Observable<string> {
376+
getDisplayStringValue(): Observable<string> {
371377
if (!this.view) {
372378
return;
373379
}
374380
let selected = this.view.getSelected();
375-
if (selected && !this.displayValue) {
381+
if (selected && (!this.displayValue || !this.isRenderString())) {
376382
if (this.type === "multi") {
377383
return of(this.placeholder);
378384
} else {
379385
return of(selected[0].content);
380386
}
381-
} else if (selected) {
382-
return of(this.displayValue);
387+
} else if (selected && this.isRenderString()) {
388+
return of(this.displayValue as string);
383389
}
384390
return of(this.placeholder);
385391
}
386392

393+
isRenderString(): boolean {
394+
return typeof this.displayValue === "string";
395+
}
396+
397+
getRenderTemplateContext() {
398+
if (!this.view) {
399+
return;
400+
}
401+
let selected = this.view.getSelected();
402+
if (this.type === "multi") {
403+
return {items: selected};
404+
} else if (selected && selected.length > 0) {
405+
return {item: selected[0]}; // this is to be compatible with the dropdown-list template
406+
} else {
407+
return {};
408+
}
409+
}
410+
387411
getSelectedCount(): number {
388412
if (this.view.getSelected()) {
389413
return this.view.getSelected().length;

src/dropdown/dropdown.stories.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,43 @@ storiesOf("Dropdown", module)
119119
theme: select("theme", ["dark", "light"], "dark")
120120
}
121121
}))
122+
.add("With Template", () => ({
123+
template: `
124+
<div style="width: 300px;">
125+
<ibm-dropdown
126+
[theme]="theme"
127+
placeholder="Select"
128+
[displayValue]="dropdownRenderer"
129+
[disabled]="disabled"
130+
(selected)="selected($event)"
131+
(onClose)="onClose($event)">
132+
<ibm-dropdown-list [items]="items" [listTpl]="dropdownRenderer"></ibm-dropdown-list>
133+
</ibm-dropdown>
134+
<ng-template #dropdownRenderer let-item="item">
135+
<div *ngIf="item && item.content" style="font-size: 14px;">
136+
<svg focusable="false" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg"
137+
width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" style="will-change: transform;">
138+
<path d="M9.3 3.7l3.8 3.8H1v1h12.1l-3.8 3.8.7.7 5-5-5-5z"></path>
139+
</svg>
140+
&nbsp;{{item.content}}
141+
</div>
142+
</ng-template>
143+
</div>
144+
`,
145+
props: {
146+
disabled: boolean("disabled", false),
147+
items: object("items", [
148+
{ content: "one", selected: true },
149+
{ content: "two" },
150+
{ content: "three" },
151+
{ content: "four" }
152+
]),
153+
selected: action("Selected fired for dropdown"),
154+
onClose: action("Dropdown closed"),
155+
theme: select("theme", ["dark", "light"], "dark")
156+
}
157+
158+
}))
122159
.add("Skeleton", () => ({
123160
template: `
124161
<div style="width: 300px">

src/slider/slider.component.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
8989
[step]="step"
9090
[min]="min"
9191
[max]="max"
92-
[value]="value">
92+
[value]="value.toString()">
9393
</div>
9494
<label [id]="topRangeId" class="bx--slider__range-label">
9595
<ng-content select="[maxLabel]"></ng-content>
@@ -189,7 +189,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
189189
protected eventSubscriptions: Array<Subscription> = [];
190190
protected slidAmount = 0;
191191
protected input: HTMLInputElement;
192-
protected _value = 0;
192+
protected _value = this.min;
193193
protected _disabled = false;
194194

195195
constructor(protected elementRef: ElementRef) {}
@@ -199,7 +199,10 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
199199
this.eventSubscriptions.push(fromEvent(document, "mousemove").subscribe(this.onMouseMove.bind(this)));
200200
this.eventSubscriptions.push(fromEvent(document, "mouseup").subscribe(this.onMouseUp.bind(this)));
201201

202-
// ODO: ontouchstart/ontouchmove/ontouchend
202+
// apply any values we got from before the view initialized
203+
this.value = this.value;
204+
205+
// TODO: ontouchstart/ontouchmove/ontouchend
203206

204207
// set up the optional input
205208
this.input = this.elementRef.nativeElement.querySelector("input:not([type=range])");

0 commit comments

Comments
 (0)