Skip to content

Commit

Permalink
Use renderer2 to manipulate elements (#687)
Browse files Browse the repository at this point in the history
* Add renderer2

* Fix tests

* Fix tests and remove addClass utility

* Remove angular v2 from testing

* Add breaking change description

* Use angular API to check class and remove element
  • Loading branch information
dxvladislavvolkov committed Feb 8, 2018
1 parent 3935094 commit a487457
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 51 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## Unreleased

### Breaking changes
Angular version 2.x is no longer supported. Now our integration library is based on the Angular Renderer2 class, which is available starting with Angular version 4 and allows manipulating DOM elements on the server side (server-side rendering).

## 17.2.5-beta.1 (2017-12-26)

### Bug Fixes
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
"license": "MIT",
"peerDependencies": {
"devextreme": "~17.2.4",
"@angular/core": ">2.4.2",
"@angular/common": ">2.4.2",
"@angular/forms": ">2.4.2"
"@angular/core": ">4.0.0",
"@angular/common": ">4.0.0",
"@angular/forms": ">4.0.0"
},
"devDependencies": {
"devextreme": "~17.2.4",
Expand Down
3 changes: 0 additions & 3 deletions shippable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,3 @@ build:
- shippable_retry npm install @angular/core@^5.0.0-rc.1 @angular/common@^5.0.0-rc.1 @angular/forms@^5.0.0-rc.1 @angular/compiler@^5.0.0-rc.1 @angular/platform-browser@^5.0.0-rc.1 @angular/platform-browser-dynamic@^5.0.0-rc.1 --unsafe-perm
- gulp build.tests
- gulp run.tests
- shippable_retry npm install @angular/core@^2.4.2 @angular/common@^2.4.2 @angular/forms@^2.4.2 @angular/compiler@^2.4.2 @angular/platform-browser@^2.4.2 @angular/platform-browser-dynamic@^2.4.2 --unsafe-perm
- gulp build.tests
- gulp run.tests
5 changes: 3 additions & 2 deletions src/core/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import {
AfterViewInit
} from '@angular/core';

import { ɵgetDOM as getDOM } from '@angular/platform-browser';

import { DxTemplateDirective } from './template';
import { IDxTemplateHost, DxTemplateHost } from './template-host';
import { EmitterHelper } from './events-strategy';
import { WatcherHelper } from './watcher-helper';
import * as events from 'devextreme/events';
import { removeElement } from './utils';
import {
INestedOptionContainer,
ICollectionNestedOption,
Expand Down Expand Up @@ -123,7 +124,7 @@ export abstract class DxComponent implements OnChanges, OnInit, DoCheck, AfterCo
let element = this.instance.element();
events.triggerHandler(element, { type: 'dxremove', _angularIntegration: true });
this.instance.dispose();
removeElement(element);
getDOM().remove(element);
}
}
constructor(protected element: ElementRef, private ngZone: NgZone, templateHost: DxTemplateHost, private watcherHelper: WatcherHelper) {
Expand Down
13 changes: 7 additions & 6 deletions src/core/nested-option.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { QueryList, ElementRef } from '@angular/core';
import { QueryList, ElementRef, Renderer2 } from '@angular/core';
import { ɵgetDOM as getDOM } from '@angular/platform-browser';

import { DX_TEMPLATE_WRAPPER_CLASS } from './template';
import { addClass, hasClass, getElement } from './utils';
import { getElement } from './utils';

import * as events from 'devextreme/events';

Expand Down Expand Up @@ -131,7 +132,7 @@ export interface IOptionWithTemplate extends BaseNestedOption {
let triggerShownEvent = function(element) {
let changeHandlers = [];

if (hasClass(element, VISIBILITY_CHANGE_SELECTOR)) {
if (getDOM().hasClass(element, VISIBILITY_CHANGE_SELECTOR)) {
changeHandlers.push(element);
}

Expand All @@ -142,7 +143,7 @@ let triggerShownEvent = function(element) {
}
};

export function extractTemplate(option: IOptionWithTemplate, element: ElementRef) {
export function extractTemplate(option: IOptionWithTemplate, element: ElementRef, renderer: Renderer2, document: any) {
if (!option.template === undefined || !element.nativeElement.hasChildNodes()) {
return;
}
Expand All @@ -164,13 +165,13 @@ export function extractTemplate(option: IOptionWithTemplate, element: ElementRef
render: (renderData) => {
let result = element.nativeElement;

addClass(result, DX_TEMPLATE_WRAPPER_CLASS);
renderer.addClass(result, DX_TEMPLATE_WRAPPER_CLASS);

if (renderData.container) {
let container = getElement(renderData.container);
let resultInContainer = container.contains(element.nativeElement);

container.appendChild(element.nativeElement);
renderer.appendChild(container, element.nativeElement);

if (!resultInContainer) {
let resultInBody = document.body.contains(container);
Expand Down
10 changes: 7 additions & 3 deletions src/core/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {
TemplateRef,
ViewContainerRef,
Input,
Renderer2,
NgZone
} from '@angular/core';

import { DxTemplateHost } from './template-host';
import { addClass, getElement } from './utils';
import { getElement } from './utils';
import * as events from 'devextreme/events';

export const DX_TEMPLATE_WRAPPER_CLASS = 'dx-template-wrapper';
Expand All @@ -34,6 +35,7 @@ export class DxTemplateDirective {
constructor(private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef,
templateHost: DxTemplateHost,
private renderer: Renderer2,
private ngZone: NgZone) {
templateHost.setTemplate(this);
}
Expand All @@ -46,7 +48,7 @@ export class DxTemplateDirective {
let container = getElement(renderData.container);
if (renderData.container) {
childView.rootNodes.forEach((element) => {
container.appendChild(element);
this.renderer.appendChild(container, element);
});
}
// =========== WORKAROUND =============
Expand All @@ -56,7 +58,9 @@ export class DxTemplateDirective {
});
// =========== /WORKAROUND =============
childView.rootNodes.forEach((element) => {
addClass(element, DX_TEMPLATE_WRAPPER_CLASS);
if (element.nodeType === 1) {
this.renderer.addClass(element, DX_TEMPLATE_WRAPPER_CLASS);
}

events.one(element, 'dxremove', (e) => {
if (!e._angularIntegration) {
Expand Down
31 changes: 0 additions & 31 deletions src/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,3 @@
export function addClass(element: any, name: string) {
if (element.nodeType === 1) {
if (element.classList) {
element.classList.add(name);
} else {
element.className = element.className ? element.className + ' ' + name : name;
}

}
};

export function hasClass(element: any, name: string) {
let result;

if (element.classList) {
result = element.classList.contains(name);
} else {
result = element.className.split(' ').indexOf(name) >= 0;
}

return result;
};

export function getElement(element: any) {
return element.get ? element.get(0) : element;
};

export function removeElement(element: any) {
let node = getElement(element),
parentNode = node && node.parentNode;
if (parentNode) {
parentNode.removeChild(node);
}
};
8 changes: 7 additions & 1 deletion templates/nested-component.tst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
NgModule,
Host,<#? it.hasTemplate #>
ElementRef,
Renderer2,
Inject,
AfterViewInit,<#?#>
SkipSelf<#? it.properties #>,
Input<#?#><#? it.collectionNestedComponents.length #>,
Expand All @@ -13,6 +15,8 @@ import {
QueryList<#?#>
} from '@angular/core';

<#? it.hasTemplate #>import { DOCUMENT } from '@angular/common';<#?#>

<#? it.isDevExpressRequired #>
import DevExpress from 'devextreme/bundles/dx.all';<#?#>

Expand Down Expand Up @@ -56,6 +60,8 @@ export class <#= it.className #>Component extends <#= it.baseClass #><#? it.hasT
<#~#>
constructor(@SkipSelf() @Host() parentOptionHost: NestedOptionHost,
@Host() optionHost: NestedOptionHost<#? it.hasTemplate #>,
private renderer: Renderer2,
@Inject(DOCUMENT) private document: any,
@Host() templateHost: DxTemplateHost,
private element: ElementRef<#?#>) {
super();
Expand All @@ -74,7 +80,7 @@ export class <#= it.className #>Component extends <#= it.baseClass #><#? it.hasT
this.template = template;
}
ngAfterViewInit() {
extractTemplate(this, this.element);
extractTemplate(this, this.element, this.renderer, this.document);
}
<#?#>
}
Expand Down
12 changes: 10 additions & 2 deletions tests/src/core/nested-option.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
ViewChildren,
NgZone,
Input,
Renderer2,
Inject,
Output,
ContentChildren,
QueryList,
Expand All @@ -15,6 +17,8 @@ import {
AfterViewInit
} from '@angular/core';

import { DOCUMENT } from '@angular/common';

import {
TestBed,
async
Expand Down Expand Up @@ -116,7 +120,11 @@ export class DxiTestCollectionOptionWithTemplateComponent extends CollectionNest

shownEventFired = false;

constructor(@SkipSelf() @Host() private _pnoh: NestedOptionHost, @Host() private _noh: NestedOptionHost, private element: ElementRef) {
constructor(@SkipSelf() @Host() private _pnoh: NestedOptionHost,
@Host() private _noh: NestedOptionHost,
private element: ElementRef,
private renderer: Renderer2,
@Inject(DOCUMENT) private document: any) {
super();

this._pnoh.setNestedOption(this);
Expand All @@ -126,7 +134,7 @@ export class DxiTestCollectionOptionWithTemplateComponent extends CollectionNest
ngAfterViewInit() {
let element = this.element.nativeElement;

extractTemplate(this, this.element);
extractTemplate(this, this.element, this.renderer, this.document);

element.classList.add('dx-visibility-change-handler');
events.on(element, 'dxshown', function() {
Expand Down

0 comments on commit a487457

Please sign in to comment.