Skip to content

Commit 24677b1

Browse files
Merge pull request #532 from DevExpress/shownevent_in_template
Fire shownEvent in template.render method of nested options after visibility changing
2 parents 5bbbbb8 + 8df7e3c commit 24677b1

File tree

2 files changed

+119
-5
lines changed

2 files changed

+119
-5
lines changed

src/core/nested-option.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ let $ = require('jquery');
55

66
import { DX_TEMPLATE_WRAPPER_CLASS } from './template';
77

8+
const VISIBILITY_CHANGE_SELECTOR = 'dx-visibility-change-handler';
9+
810
export interface INestedOptionContainer {
911
instance: any;
1012
}
@@ -142,13 +144,40 @@ export function extractTemplate(option: OptionWithTemplate, element: ElementRef)
142144
return;
143145
}
144146

147+
function triggerShownEvent($element) {
148+
let changeHandlers = $();
149+
150+
if ($element.hasClass(VISIBILITY_CHANGE_SELECTOR)) {
151+
changeHandlers = $element;
152+
}
153+
154+
changeHandlers = changeHandlers.add($element.find('.' + VISIBILITY_CHANGE_SELECTOR));
155+
156+
for (let i = 0; i < changeHandlers.length; i++) {
157+
$(changeHandlers[i]).triggerHandler('dxshown');
158+
}
159+
}
160+
145161
option.template = {
146162
render: (renderData) => {
163+
let $result = $(element.nativeElement).addClass(DX_TEMPLATE_WRAPPER_CLASS);
164+
147165
if (renderData.container) {
166+
let container = renderData.container.get(0);
167+
let resultInContainer = container.contains(element.nativeElement);
168+
148169
renderData.container.append(element.nativeElement);
170+
171+
if (!resultInContainer) {
172+
let resultInBody = document.body.contains(container);
173+
174+
if (resultInBody) {
175+
triggerShownEvent($result);
176+
}
177+
}
149178
}
150-
return $(element.nativeElement)
151-
.addClass(DX_TEMPLATE_WRAPPER_CLASS);
179+
180+
return $result;
152181
}
153182
};
154183
}

tests/src/core/nested-option.spec.ts

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ import {
2929
import {
3030
NestedOption,
3131
CollectionNestedOption,
32-
NestedOptionHost
32+
NestedOptionHost,
33+
extractTemplate
3334
} from '../../../dist/core/nested-option';
3435

36+
let $ = require('jquery');
37+
3538
// TODO: Try to replace dxButton to Widget ('require' required)
3639
import DxButton from 'devextreme/ui/button';
3740
let DxTestWidget = DxButton['inherit']({
@@ -94,6 +97,46 @@ export class DxiTestCollectionOptionComponent extends CollectionNestedOption {
9497
}
9598
}
9699

100+
@Component({
101+
selector: 'dxi-test-collection-option-with-template',
102+
template: '<ng-content></ng-content>',
103+
providers: [NestedOptionHost]
104+
})
105+
export class DxiTestCollectionOptionWithTemplateComponent extends CollectionNestedOption implements AfterViewInit {
106+
protected get _optionPath() {
107+
return 'testCollectionWithTemplateOption';
108+
}
109+
110+
get template() {
111+
return this._getOption('template');
112+
}
113+
set template(value: any) {
114+
this._setOption('template', value);
115+
}
116+
117+
shownEventFired = false;
118+
119+
constructor(@SkipSelf() @Host() private _pnoh: NestedOptionHost, @Host() private _noh: NestedOptionHost, private element: ElementRef) {
120+
super();
121+
122+
this._pnoh.setNestedOption(this);
123+
this._noh.setHost(this, this._fullOptionPath.bind(this));
124+
}
125+
126+
ngAfterViewInit() {
127+
let $element = $(this.element.nativeElement);
128+
129+
extractTemplate(this, this.element);
130+
131+
$element.addClass('dx-visibility-change-handler');
132+
$element.on('dxshown', function() {
133+
this.shownEventFired = true;
134+
}.bind(this));
135+
136+
this.template.render({ container: $('dx-test-widget') });
137+
}
138+
}
139+
97140
@Component({
98141
selector: 'dx-test-widget',
99142
template: '',
@@ -114,6 +157,13 @@ export class DxTestWidgetComponent extends DxComponent implements AfterViewInit
114157
set testCollectionOption(value: any) {
115158
this._setOption('testCollectionOption', value);
116159
};
160+
@Input()
161+
get testCollectionOptionWithTemplate(): any {
162+
return this._getOption('testCollectionOptionWithTemplate');
163+
}
164+
set testCollectionOptionWithTemplate(value: any) {
165+
this._setOption('testCollectionOptionWithTemplate', value);
166+
};
117167

118168
@ContentChildren(DxiTestCollectionOptionComponent)
119169
get testCollectionOptionChildren(): QueryList<DxiTestCollectionOptionComponent> {
@@ -123,9 +173,21 @@ export class DxTestWidgetComponent extends DxComponent implements AfterViewInit
123173
this.setChildren('testCollectionOption', value);
124174
}
125175

176+
@ContentChildren(DxiTestCollectionOptionWithTemplateComponent)
177+
get testCollectionOptionWithTemplateChildren(): QueryList<DxiTestCollectionOptionWithTemplateComponent> {
178+
return this._getOption('testCollectionOptionWithTemplate');
179+
}
180+
set testCollectionOptionWithTemplateChildren(value) {
181+
this.setChildren('testCollectionOptionWithTemplate', value);
182+
}
183+
184+
@ContentChildren(DxiTestCollectionOptionWithTemplateComponent)
185+
testCollectionOptionWithTemplateChildrens: QueryList<DxiTestCollectionOptionWithTemplateComponent>;
186+
126187
@Output() onOptionChanged = new EventEmitter<any>();
127188
@Output() testOptionChange = new EventEmitter<any>();
128189
@Output() testCollectionOptionChange = new EventEmitter<any>();
190+
@Output() testCollectionOptionWithTemplateChange = new EventEmitter<any>();
129191

130192
constructor(elementRef: ElementRef, ngZone: NgZone, templateHost: DxTemplateHost, private _noh: NestedOptionHost,
131193
_watcherHelper: WatcherHelper) {
@@ -134,7 +196,8 @@ export class DxTestWidgetComponent extends DxComponent implements AfterViewInit
134196
this._events = [
135197
{ subscribe: 'optionChanged', emit: 'onOptionChanged' },
136198
{ emit: 'testOptionChange' },
137-
{ emit: 'testCollectionOptionChange' }
199+
{ emit: 'testCollectionOptionChange' },
200+
{ emit: 'testCollectionOptionWithTemplate' }
138201
];
139202

140203
this._noh.setHost(this);
@@ -168,7 +231,8 @@ describe('DevExtreme Angular widget', () => {
168231
TestContainerComponent,
169232
DxTestWidgetComponent,
170233
DxoTestOptionComponent,
171-
DxiTestCollectionOptionComponent
234+
DxiTestCollectionOptionComponent,
235+
DxiTestCollectionOptionWithTemplateComponent
172236
]
173237
});
174238
});
@@ -238,4 +302,25 @@ describe('DevExtreme Angular widget', () => {
238302
expect(instance.option('testCollectionOption')[0].testOption).toEqual({ testNestedOption: 'text' });
239303
}));
240304

305+
it('method template.render of nested option should trigger shownEvent after rendering', async(() => {
306+
TestBed.overrideComponent(TestContainerComponent, {
307+
set: {
308+
template: `
309+
<dx-test-widget>
310+
<dxi-test-collection-option-with-template>
311+
<div>123</div>
312+
</dxi-test-collection-option-with-template>
313+
</dx-test-widget>
314+
`
315+
}
316+
});
317+
let fixture = TestBed.createComponent(TestContainerComponent);
318+
fixture.detectChanges();
319+
320+
let innerWidget = fixture.componentInstance.innerWidgets.first;
321+
let nestedOption = innerWidget.testCollectionOptionWithTemplateChildrens.first;
322+
323+
expect(nestedOption.shownEventFired).toBe(true);
324+
}));
325+
241326
});

0 commit comments

Comments
 (0)