Skip to content

Commit

Permalink
DevExtreme widgets should render templates within Angular Zone (#882) (
Browse files Browse the repository at this point in the history
…#883)

DevExtreme widgets should render templates within Angular Zone (#882)
  • Loading branch information
ovchinnikov committed Oct 25, 2018
1 parent 1a802cf commit d8f4ae0
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
36 changes: 27 additions & 9 deletions src/core/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
TemplateRef,
ViewContainerRef,
Input,
Renderer2
Renderer2,
NgZone,
EmbeddedViewRef
} from '@angular/core';

import { DxTemplateHost } from './template-host';
Expand Down Expand Up @@ -34,25 +36,41 @@ export class DxTemplateDirective {
constructor(private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef,
templateHost: DxTemplateHost,
private renderer: Renderer2) {
private renderer: Renderer2,
private zone: NgZone) {
templateHost.setTemplate(this);
}

render(renderData: RenderData) {
let childView = this.viewContainerRef.createEmbeddedView(this.templateRef, {
private renderTemplate(renderData: RenderData): EmbeddedViewRef<any> {
const childView = this.viewContainerRef.createEmbeddedView(this.templateRef, {
'$implicit': renderData.model,
index: renderData.index
});
let container = getElement(renderData.container);

const container = getElement(renderData.container);
if (renderData.container) {
childView.rootNodes.forEach((element) => {
this.renderer.appendChild(container, element);
});
}
// =========== WORKAROUND =============
// https://github.com/angular/angular/issues/12243
childView['detectChanges']();
// =========== /WORKAROUND =============

return childView;
}

render(renderData: RenderData) {
let childView;
if (this.zone.isStable) {
childView = this.zone.run(() => {
return this.renderTemplate(renderData);
});
} else {
childView = this.renderTemplate(renderData);
// =========== WORKAROUND =============
// https://github.com/angular/angular/issues/12243
childView['detectChanges']();
// =========== /WORKAROUND =============
}

childView.rootNodes.forEach((element) => {
if (element.nodeType === 1) {
this.renderer.addClass(element, DX_TEMPLATE_WRAPPER_CLASS);
Expand Down
40 changes: 37 additions & 3 deletions tests/src/core/template.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,21 @@ export class DxTestComponent extends DxComponent implements AfterViewInit {
return new DxTestWidget(element, options);
}

ngAfterViewInit() {
renderTemplate(model) {
const element = this.element.nativeElement;
element.textContent = '';
this.templates[0].render({
model: {},
container: this.element.nativeElement,
model: model,
container: element,
index: 5
});
}

ngAfterViewInit() {
this.renderTemplate({
value: () => ''
});
}
}

@Component({
Expand All @@ -109,6 +117,7 @@ export class DxTestComponent extends DxComponent implements AfterViewInit {
})
export class TestContainerComponent {
@ViewChild(DxTestWidgetComponent) widget: DxTestWidgetComponent;
@ViewChild(DxTestComponent) testComponent: DxTestComponent;

@Output() onInnerElementClicked = new EventEmitter<any>();

Expand Down Expand Up @@ -193,5 +202,30 @@ describe('DevExtreme Angular widget\'s template', () => {
expect(element.textContent).toBe('index: 5');
});

it('should be created within Angular Zone', () => {
TestBed.overrideComponent(TestContainerComponent, {
set: {
template: `
<dx-test>
<div *dxTemplate="let d of 'templateName'">
<div class="elem" (click)="d.value()"></div>
</div>
</dx-test>
`}
});

let fixture = TestBed.createComponent(TestContainerComponent);
fixture.detectChanges();

fixture.ngZone.runOutsideAngular(() => {
fixture.componentInstance.testComponent.renderTemplate({
value: () => {
expect(fixture.ngZone.isStable).toBe(false);
}
});
});

fixture.nativeElement.querySelector('.elem').click();
});
});

0 comments on commit d8f4ae0

Please sign in to comment.