Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit 4cf53ab

Browse files
committed
Merge branch 'master'
Conflicts: package.json
2 parents 78be220 + 0468883 commit 4cf53ab

File tree

17 files changed

+149
-106
lines changed

17 files changed

+149
-106
lines changed

bootstrapper/popup/popupNg2.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ <h3>Popup content</h3>
1818
<div *rlDialogHeader>Header 2</div>
1919
<div *rlDialogContent>
2020
<rlTextbox label="Textbox" name="textbox" rlRequired="Required"></rlTextbox>
21+
<rlSelect label="Select" name="select" [options]="options" rlRequired="Required" nullOption="None"></rlSelect>
22+
<rlTypeahead label="Typeahead" name="typeahead" [getItems]="getOptions" rlRequired="Required" allowCollapse="true" [create]="create"></rlTypeahead>
2123
</div>
2224
</rlDialog>
2325
<rlPromptDialog #prompt

bootstrapper/popup/popupNg2Bootstrapper.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Component } from '@angular/core';
2+
import { Observable } from 'rxjs';
23

34
import { IDialogClosingHandler } from '../../source/components/dialog/dialogRoot.service';
45

@@ -9,6 +10,8 @@ import { IDialogClosingHandler } from '../../source/components/dialog/dialogRoot
910
export class PopupBootstrapper {
1011
content: string = 'Some content';
1112
onClosing: IDialogClosingHandler;
13+
options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
14+
getOptions = () => Observable.of(this.options);
1215

1316
constructor() {
1417
this.onClosing = () => {
@@ -28,4 +31,6 @@ export class PopupBootstrapper {
2831
save = (data) => {
2932
console.log(data);
3033
}
31-
}
34+
35+
create = x => x;
36+
}

source/behaviors/offClick/offClick.ts

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { Directive, Host, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
1+
import { Directive, Host, Input, Output, EventEmitter, OnInit, OnDestroy, SimpleChanges } from '@angular/core';
22

33
import { services } from 'typescript-angular-utilities';
44
import __guid = services.guid;
55

6+
import { DocumentWrapper } from '../../services/document/document.provider';
7+
68
export interface IOffClickEvent extends MouseEvent {
79
rlEventIdentifier: string;
810
}
@@ -16,29 +18,53 @@ export interface IOffClickEvent extends MouseEvent {
1618
export class OffClickDirective implements OnInit, OnDestroy {
1719
@Output('offClick') offClick: EventEmitter<any> = new EventEmitter();
1820

21+
private _active: boolean = true;
22+
@Input('offClickActive') set active(value: boolean)
23+
{
24+
if (value) {
25+
this.addListener();
26+
} else {
27+
this.removeListener();
28+
}
29+
this._active = value;
30+
}
31+
1932
listener: { ($event: MouseEvent): void } = ($event: IOffClickEvent) => {
2033
if ($event.rlEventIdentifier !== this.identifier) {
2134
this.offClick.emit($event);
2235
}
2336
};
2437

2538
identifier: string;
39+
document: Document;
2640

27-
constructor(guidService: __guid.GuidService) {
41+
constructor(guidService: __guid.GuidService
42+
, document: DocumentWrapper) {
2843
this.identifier = guidService.random();
44+
this.document = <any>document;
2945
}
3046

3147
ngOnInit() {
32-
setTimeout(() => {
33-
document.addEventListener('click', this.listener);
34-
}, 0);
48+
if (this._active) {
49+
setTimeout(() => {
50+
this.addListener();
51+
});
52+
}
53+
}
54+
55+
addListener(): void {
56+
this.document.addEventListener('click', this.listener);
57+
}
58+
59+
removeListener(): void {
60+
this.document.removeEventListener('click', this.listener);
3561
}
3662

3763
ngOnDestroy() {
38-
document.removeEventListener('click', this.listener);
64+
this.removeListener();
3965
}
4066

4167
onClick($event: IOffClickEvent) {
4268
$event.rlEventIdentifier = this.identifier;
4369
}
44-
}
70+
}

source/componentProviders.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { MergeSort } from './components/cardContainer/sorts/mergeSort/mergeSort.
1515

1616
import { AsyncHelper } from './services/async/async.service';
1717
import { AutosaveActionService } from './services/autosaveAction/autosaveAction.service';
18+
import { DOCUMENT_PROVIDER } from './services/document/document.provider';
1819
import { DocumentService } from './services/documentWrapper/documentWrapper.service';
1920
import { FormService } from './services/form/form.service';
2021
import { JQUERY_PROVIDER } from './services/jquery/jquery.provider';
@@ -66,8 +67,9 @@ const defaultThemeNg1: FactoryProvider = {
6667
DefaultTheme,
6768
defaultThemeNg1,
6869
DialogRootService,
69-
FormService,
70+
DOCUMENT_PROVIDER,
7071
DocumentService,
72+
FormService,
7173
BreakpointService,
7274
VisibleBreakpointService,
7375
JQUERY_PROVIDER,

source/components/inputs/select/select.html

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,29 @@
33
[class.error]="componentValidator.error$ | async"
44
[class.rl-select-loading]="busy?.loading">
55
<label [@slide]="labelState">{{label}}</label>
6-
<div class="form-control rl-select-trigger"
7-
[class.disabled]="disabled"
8-
[class.rl-select-open]="list.showOptions"
9-
(focus)="showLabel()"
10-
(blur)="hideLabelIfEmpty()"
11-
tabindex="0"
12-
rlPopoutTrigger>
13-
<span class="placeholder"
14-
[class.hide-placeholder]="hidePlaceholder"
15-
[hidden]="value">{{label}}</span>
16-
<span class="rl-select-choice">{{getDisplayName(value)}}</span>
6+
<div class="rl-select-wrap"
7+
(offClick)="list.close()"
8+
[offClickActive]="list.showOptions">
9+
<div class="form-control rl-select-trigger"
10+
[class.disabled]="disabled"
11+
[class.rl-select-open]="list.showOptions"
12+
(focus)="showLabel()"
13+
(blur)="hideLabelIfEmpty()"
14+
tabindex="0"
15+
rlPopoutTrigger>
16+
<span class="placeholder"
17+
[class.hide-placeholder]="hidePlaceholder"
18+
[hidden]="value">{{label}}</span>
19+
<span class="rl-select-choice">{{getDisplayName(value)}}</span>
20+
</div>
21+
<rlPopoutList #list
22+
[options]="options"
23+
[template]="template"
24+
[transform]="transform"
25+
(select)="select($event)">
26+
<rlPopoutItem class="rl-select-option-null" *ngIf="nullOption" (trigger)="select(null)">{{nullOption}}</rlPopoutItem>
27+
</rlPopoutList>
1728
</div>
18-
<rlPopoutList #list
19-
[options]="options"
20-
[template]="template"
21-
[transform]="transform"
22-
(select)="select($event)">
23-
<rlPopoutItem class="rl-select-option-null" *ngIf="nullOption" (trigger)="select(null)">{{nullOption}}</rlPopoutItem>
24-
</rlPopoutList>
2529
<rlBusy [loading]="!options"></rlBusy>
2630
<div *ngIf="componentValidator.error$ | async" class="error-string">
2731
{{componentValidator.error$ | async}}

source/components/inputs/select/select.ng1.html

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
<label ng-show="select.selection" class="label-slide angular-animate">
33
{{::select.label}}
44
</label>
5-
<div class="form-control rl-select-trigger"
6-
ng-class="{ 'disabled': select.ngDisabled, 'rl-select-open': select.showOptions }"
7-
ng-mousedown="select.toggle()"
8-
ng-blur="select.close()"
9-
tabindex="0">
10-
<span class="placeholder" ng-hide="select.selection">{{::select.label}}</span>
11-
<span class="rl-select-choice">{{select.getDisplayName(select.selection)}}</span>
5+
<div class="rl-select-wrap" tabindex="0" ng-blur="select.close()">
6+
<div class="form-control rl-select-trigger"
7+
ng-class="{ 'disabled': select.ngDisabled, 'rl-select-open': select.showOptions }"
8+
ng-mousedown="select.toggle()">
9+
<span class="placeholder" ng-hide="select.selection">{{::select.label}}</span>
10+
<span class="rl-select-choice">{{select.getDisplayName(select.selection)}}</span>
11+
</div>
12+
<ul class="rl-select-list" ng-if="select.showOptions">
13+
<li class="rl-select-option rl-select-option-null" ng-if="::select.nullOption" ng-mousedown="select.selectOption(null)">{{::select.nullOption}}</li>
14+
<li class="rl-select-option"
15+
ng-repeat="$item in select.options"
16+
ng-mousedown="select.selectOption($item)">
17+
<rl-template-renderer template="select.template" rl-alias="$item as {{select.itemAs}}"></rl-template-renderer>
18+
</li>
19+
</ul>
1220
</div>
13-
<ul class="rl-select-list" ng-if="select.showOptions">
14-
<li class="rl-select-option rl-select-option-null" ng-if="::select.nullOption" ng-mousedown="select.selectOption(null)">{{::select.nullOption}}</li>
15-
<li class="rl-select-option"
16-
ng-repeat="$item in select.options"
17-
ng-mousedown="select.selectOption($item)">
18-
<rl-template-renderer template="select.template" rl-alias="$item as {{select.itemAs}}"></rl-template-renderer>
19-
</li>
20-
</ul>
2121
<rl-busy loading="select.loading"></rl-busy>
2222
<span class="error-string angular-animate" ng-if="select.inputValidator.error | isEmpty:false">{{select.inputValidator.error}}</span>
2323
</div>

source/components/inputs/select/select.tests.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,18 @@ describe('SelectComponent', () => {
4444
];
4545
});
4646

47-
it('should set the value and close the options', (): void => {
48-
const closeSpy = sinon.spy();
49-
dropdown.list = <any>{
50-
close: closeSpy,
51-
};
52-
47+
it('should set the value', (): void => {
5348
dropdown.select(options[1]);
5449

55-
sinon.assert.calledOnce(closeSpy);
5650
sinon.assert.calledOnce(setValue);
5751
sinon.assert.calledWith(setValue, options[1]);
5852
});
5953

60-
it('should close the options without setting the value if the current value is reselected', (): void => {
61-
const closeSpy = sinon.spy();
62-
dropdown.list = <any>{
63-
close: closeSpy,
64-
};
54+
it('should not set the value if the current value is reselected', (): void => {
6555
dropdown.value = options[1];
6656

6757
dropdown.select(options[1]);
6858

69-
sinon.assert.calledOnce(closeSpy);
7059
sinon.assert.notCalled(setValue);
7160
});
7261

source/components/inputs/select/select.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export class SelectComponent<T> extends ValidatedInputComponent<T> implements Af
3131
@Input() externalTemplate: TemplateRef<any>;
3232

3333
@ViewChild(BusyComponent) busy: BusyComponent;
34-
@ViewChild(PopoutListComponent) list: PopoutListComponent<T>;
3534
@ContentChild(TemplateRef) template: TemplateRef<any>;
3635

3736
private transformService: __transform.ITransformService;
@@ -56,7 +55,6 @@ export class SelectComponent<T> extends ValidatedInputComponent<T> implements Af
5655
if (value != this.value) {
5756
this.setValue(value);
5857
}
59-
this.list.close();
6058
this.hideLabelIfEmpty();
6159
}
6260

source/components/inputs/typeahead/typeahead.html

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,29 @@
33
[class.error]="componentValidator.error$ | async">
44
<label [@slide]="labelState">{{label}}</label>
55
<div [hidden]="collapsed">
6-
<input class="form-control rl-select-trigger"
7-
#input
8-
type="text"
9-
[disabled]="disabled"
10-
[class.rl-select-open]="list.showOptions"
11-
[class.hide-placeholder]="hidePlaceholder"
12-
[placeholder]="placeholder"
13-
[value]="search"
14-
(focus)="showLabel()"
15-
(blur)="hideLabelIfEmpty()"
16-
rlPopoutTrigger
17-
(input)="searchStream.next($event.target.value)" />
18-
<rlPopoutList [disabled]="!canShowOptions"
19-
[options]="visibleItems$ | async"
20-
[template]="template"
21-
[transform]="transform"
22-
(select)="selectItem($event)">
23-
<rlPopoutItem class="rl-select-option-custom" *ngIf="allowCustomOption" (trigger)="selectCustom()">{{search}}</rlPopoutItem>
24-
</rlPopoutList>
6+
<div class="rl-select-wrap"
7+
(offClick)="list.close()"
8+
[offClickActive]="list.showOptions || false">
9+
<input class="form-control rl-select-trigger"
10+
#input
11+
type="text"
12+
[disabled]="disabled"
13+
[class.rl-select-open]="list.showOptions"
14+
[class.hide-placeholder]="hidePlaceholder"
15+
[placeholder]="placeholder"
16+
[value]="search"
17+
(input)="searchStream.next($event.target.value)"
18+
(focus)="showLabel()"
19+
(blur)="hideLabelIfEmpty()"
20+
rlPopoutTrigger />
21+
<rlPopoutList [disabled]="!canShowOptions"
22+
[options]="visibleItems$ | async"
23+
[template]="template"
24+
[transform]="transform"
25+
(select)="selectItem($event)">
26+
<rlPopoutItem class="rl-select-option-custom" *ngIf="allowCustomOption" (trigger)="selectCustom()">{{search}}</rlPopoutItem>
27+
</rlPopoutList>
28+
</div>
2529
</div>
2630
<div class="collapsed" [hidden]="!collapsed">
2731
<span>{{getDisplayName(value)}}</span>

source/components/inputs/typeahead/typeahead.tests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ describe('TypeaheadComponent', () => {
3838
validate: sinon.spy(() => Observable.empty()),
3939
};
4040

41-
typeahead = new TypeaheadComponent(__transform.transform, null, validator, __object.objectUtility, __array.arrayUtility, __guid.guid, __search.searchUtility);
41+
const changeDetectorMock = { detectChanges: sinon.spy() };
42+
typeahead = new TypeaheadComponent(__transform.transform, null, validator, __object.objectUtility, __array.arrayUtility, __guid.guid, __search.searchUtility, <any>changeDetectorMock);
4243

4344
setValue = sinon.spy();
4445
typeahead.setValue = setValue;

source/components/inputs/typeahead/typeahead.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, Input, Output, EventEmitter, Optional, OnInit, OnChanges, SimpleChange, ViewChild, ContentChild, TemplateRef, ElementRef } from '@angular/core';
1+
import { Component, Input, Output, EventEmitter, Optional, OnInit, OnChanges, SimpleChange, ViewChild, ContentChild, TemplateRef, ElementRef, ChangeDetectorRef } from '@angular/core';
22
import { Observable, BehaviorSubject, Subject } from 'rxjs';
33
import { find, filter, isEqual, cloneDeep } from 'lodash';
44

@@ -64,6 +64,7 @@ export class TypeaheadComponent<T> extends ValidatedInputComponent<T> implements
6464

6565
transformService: __transform.ITransformService;
6666
searchUtility: __search.ISearchUtility;
67+
changeDetector: ChangeDetectorRef;
6768

6869
get visibleItems$(): Observable<T[]> {
6970
return this._visibleItems.asObservable();
@@ -83,10 +84,12 @@ export class TypeaheadComponent<T> extends ValidatedInputComponent<T> implements
8384
, object: __object.ObjectUtility
8485
, array: __array.ArrayUtility
8586
, guid: __guid.GuidService
86-
, searchService: __search.SearchUtility) {
87+
, searchService: __search.SearchUtility
88+
, changeDetector: ChangeDetectorRef) {
8789
super(rlForm, componentValidator, object, array, guid);
8890
this.transformService = transformService;
8991
this.searchUtility = searchService;
92+
this.changeDetector = changeDetector;
9093
this.inputType = 'typeahead';
9194
this.search = '';
9295
this._visibleItems = new BehaviorSubject(null);
@@ -116,7 +119,6 @@ export class TypeaheadComponent<T> extends ValidatedInputComponent<T> implements
116119
}
117120

118121
selectItem(item: T): void {
119-
this.list.close();
120122
this.search = '';
121123

122124
this.selector.emit(item);
@@ -145,6 +147,7 @@ export class TypeaheadComponent<T> extends ValidatedInputComponent<T> implements
145147
if (!isEqual(data, this.cacheDisplayList)) {
146148
this.list.open();
147149
this.cacheDisplayList = cloneDeep(data);
150+
this.changeDetector.detectChanges();
148151
return this._visibleItems.next(this.cacheDisplayList);
149152
}
150153
});
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<li class="rl-select-option"
22
[class.focused]="focused"
33
(mouseover)="focus()"
4-
(mouseleave)="blur()">
4+
(mouseleave)="blur()"
5+
(click)="select()">
56
<ng-content></ng-content>
6-
</li>
7+
</li>

source/components/popoutList/popoutItem.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ export class PopoutItemComponent<T> {
2626
blur(): void {
2727
this.list.blur();
2828
}
29+
30+
select(): void {
31+
this.list.selectCurrent();
32+
}
2933
}

0 commit comments

Comments
 (0)