Repository: DevExpress/devextreme-react (js)

Issue:
SlideOutView doesn't support scrollable content
<!--
  Note: if the issue is a general React question, please check React Docs first: https://reactjs.org/docs
  If your question is about  DevExtreme widgets' APIs, use the DevExpress Support Center: https://www.devexpress.com/Support/Center
-->

### Issue Type
<!-- E.g. 'question', 'bug report', 'feature request' -->
"bug report"
### Description
<!-- Specify what exactly the issue is related to (e.g. a component name) -->
The issue is related to SlideOutView

#### Steps to Reproduce
<!-- If the current behavior is a bug, please provide the steps to reproduce -->
See demo to reproduce: 
1) Pay attention to .dx-template-wrapper height. It is equal "auto" and prevent children with % as size
#### Current Behavior

#### Expected Behavior

#### Demo
<!--
  If you provide a minimal demo of the problem\proposal, it helps us to solve it much faster.
  Paste the link to your online code editor (like https://stackblitz.com) below:
-->
https://stackblitz.com/edit/devextreme-react-c7t368?file=index.js
### Environment Details
<!--
Specify DevExtreme version, DevExtreme React Components version, React version and other environment details or notes you consider important.
-->
- devextreme version: 18.1.6-pre-18220
- devextreme-react version:  18.1.5-alpha.10 (regression, was OK in the alpha.9)
- react version: 16.4.2


Pull request description:
Rework template removing
1) Remove `dx-template-wrapper` class
2) Add special `span` near user content to listen dx `remove` event
Fix #188 

Patch:
diff --git a/src/core/template-helper.ts b/src/core/template-helper.ts
index f56c9aa..3a78c16 100644
--- a/src/core/template-helper.ts
+++ b/src/core/template-helper.ts
@@ -83,25 +83,11 @@ function getTemplateOptions(meta: IIntegrationDescr): {
     };
 }
 
-function prepareContainer(container: Element): Element {
-    container = unwrapElement(container);
-
-    if (container.nodeName === "TABLE" ) {
-        return container;
-    }
-
-    const result = document.createElement("div");
-    result.classList.add("dx-template-wrapper");
-    container.appendChild(result);
-
-    return result;
-}
-
 function wrapTemplate(templateDescr: ITemplateDescr, stateUpdater: StateUpdater): IDxTemplate {
     return {
         render: (data: IDxTemplateData) => {
             const templateId = "__template_" + generateID();
-            const container = prepareContainer(data.container);
+            const container = unwrapElement(data.container);
             const createWrapper = (nestedTemplates) => {
                 const propsGetter = templateDescr.isNested
                     ? (prop) => nestedTemplates[templateDescr.name][prop]
diff --git a/src/core/template-wrapper.ts b/src/core/template-wrapper.ts
index 87c3927..b338452 100644
--- a/src/core/template-wrapper.ts
+++ b/src/core/template-wrapper.ts
@@ -13,9 +13,19 @@ interface ITemplateWrapperProps {
 }
 
 class TemplateWrapper extends React.PureComponent<ITemplateWrapperProps> {
+    private _removalListener: HTMLDivElement;
 
     public render() {
-        return ReactDOM.createPortal(this.props.content, this.props.container);
+        return ReactDOM.createPortal(
+            React.createElement(React.Fragment,
+                null,
+                this.props.content,
+                React.createElement(this.props.container.nodeName === "TABLE" ? "tbody" : "span", {
+                    style: { display: "none" },
+                    ref: (element: HTMLDivElement) => this._removalListener = element
+                }),
+            )
+        , this.props.container);
     }
 
     public componentDidMount() {
@@ -29,8 +39,9 @@ class TemplateWrapper extends React.PureComponent<ITemplateWrapperProps> {
             if (node) {
                 this.props.container.appendChild(node);
             }
+            this.props.container.appendChild(this._removalListener);
         };
-        events.one(this.props.container, DX_REMOVE_EVENT, () => {
+        events.one(this._removalListener, DX_REMOVE_EVENT, () => {
             restoreRemovedContent();
             this.props.onRemoved();
         });


Test patch:
diff --git a/src/core/__tests__/template.test.tsx b/src/core/__tests__/template.test.tsx
index d462da9..2dbd71b 100644
--- a/src/core/__tests__/template.test.tsx
+++ b/src/core/__tests__/template.test.tsx
@@ -95,7 +95,7 @@ describe("function template", () => {
         const container = document.createElement("div");
         renderItemTemplate("with data", container);
         component.update();
-        expect(container.innerHTML).toBe('<div class="dx-template-wrapper"><div>Template with data</div></div>');
+        expect(container.innerHTML).toBe('<div>Template with data</div><span style=\"display: none;\"></span>');
     });
 
     it("renders template for table", () => {
@@ -107,7 +107,7 @@ describe("function template", () => {
         renderItemTemplate("with data", container);
         component.update();
         expect(container.innerHTML)
-            .toBe("<tbody><tr><td>Template with data</td></tr></tbody>");
+            .toBe("<tbody><tr><td>Template with data</td></tr></tbody><tbody style=\"display: none;\"></tbody>");
     });
 
     it("calls onRendered callback", () => {
@@ -439,11 +439,15 @@ it("removes deleted nodes from state", () => {
     expect(Object.getOwnPropertyNames(component.state("templates")).length).toBe(1);
     component.update();
     const templateContent = component.find(".template").getDOMNode();
+
     const parentElement = templateContent.parentElement;
     if (!parentElement) { throw new Error(); }
 
+    const removeListener = parentElement.getElementsByTagName("SPAN")[0];
+
+    parentElement.removeChild(removeListener);
     parentElement.removeChild(templateContent);
-    events.triggerHandler(parentElement, "dxremove");
+    events.triggerHandler(removeListener, "dxremove");
     component.update();
     expect(Object.getOwnPropertyNames(component.state("templates")).length).toBe(0);
 });