8
0
Просмотр исходного кода

Allowed native DOM nodes as children of a Template.

Aleksander Nowodzinski 8 лет назад
Родитель
Сommit
76f714f6ca
2 измененных файлов с 58 добавлено и 9 удалено
  1. 15 7
      packages/ckeditor5-ui/src/template.js
  2. 43 2
      packages/ckeditor5-ui/tests/template.js

+ 15 - 7
packages/ckeditor5-ui/src/template.js

@@ -16,6 +16,7 @@ import View from './view';
 import ViewCollection from './viewcollection';
 import cloneDeepWith from '@ckeditor/ckeditor5-utils/src/lib/lodash/cloneDeepWith';
 import isObject from '@ckeditor/ckeditor5-utils/src/lib/lodash/isObject';
+import isDomNode from '@ckeditor/ckeditor5-utils/src/dom/isdomnode';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 
 const xhtmlNs = 'http://www.w3.org/1999/xhtml';
@@ -98,12 +99,13 @@ export default class Template {
 		 */
 
 		/**
-		 * Children of the template, sub–templates. Each one is an independent
-		 * instance of {@link ~Template}.
+		 * Children of the template. They can be either:
+		 * * an independent instances of {@link ~Template} (sub–templates),
+		 * * native DOM Nodes.
 		 *
 		 * **Note**: This property only makes sense when {@link #tag} is defined.
 		 *
-		 * @member {Array.<module:ui/template~Template>} #children
+		 * @member {Array.<module:ui/template~Template|Node>} #children
 		 */
 
 		/**
@@ -701,6 +703,8 @@ export default class Template {
 
 					container.appendChild( child.element );
 				}
+			} else if ( isDomNode( child ) ) {
+				container.appendChild( child );
 			} else {
 				if ( isApplying ) {
 					const revertData = data.revertData;
@@ -1173,7 +1177,7 @@ function normalize( def ) {
 				children.push( def.children );
 			} else {
 				for ( const child of def.children ) {
-					if ( isTemplate( child ) || isView( child ) ) {
+					if ( isTemplate( child ) || isView( child ) || isDomNode( child ) ) {
 						children.push( child );
 					} else {
 						children.push( new Template( child ) );
@@ -1485,11 +1489,12 @@ function shouldExtend( attrName ) {
  *			}
  *		} );
  *
- * A {@link module:ui/view~View} or another {@link module:ui/template~Template} can also become a child
- * of a template. In case of a view {@link module:ui/view~View#element} is used:
+ * A {@link module:ui/view~View}, another {@link module:ui/template~Template} or a native DOM node
+ * can also become a child of a template. When a view is passed, its {@link module:ui/view~View#element} is used:
  *
  *		const view = new SomeView();
  *		const childTemplate = new Template( { ... } );
+ *		const childNode = document.createElement( 'b' );
  *
  *		new Template( {
  *			tag: 'p',
@@ -1499,7 +1504,10 @@ function shouldExtend( attrName ) {
  *				view,
  *
  * 				// The output of childTemplate.render() will be added here.
- *				childTemplate
+ *				childTemplate,
+ *
+ *				// Native DOM nodes are included directly in the rendered output.
+ *				childNode
  *			]
  *		} );
  *

+ 43 - 2
packages/ckeditor5-ui/tests/template.js

@@ -28,6 +28,11 @@ describe( 'Template', () => {
 
 		it( 'accepts and normalizes the definition', () => {
 			const bind = Template.bind( new Model( {} ), Object.create( DomEmitterMixin ) );
+			const childNode = document.createElement( 'div' );
+			const childTemplate = new Template( {
+				tag: 'b'
+			} );
+
 			const tpl = new Template( {
 				tag: 'p',
 				attributes: {
@@ -48,7 +53,9 @@ describe( 'Template', () => {
 					'abc',
 					{
 						text: [ 'a', 'b' ]
-					}
+					},
+					childNode,
+					childTemplate
 				],
 				on: {
 					'a@span': bind.to( 'b' ),
@@ -65,12 +72,14 @@ describe( 'Template', () => {
 			expect( tpl.attributes.b[ 1 ] ).to.equal( 'baz' );
 			expect( tpl.attributes.c[ 0 ].value[ 0 ] ).to.be.instanceof( TemplateToBinding );
 
-			expect( tpl.children ).to.have.length( 4 );
+			expect( tpl.children ).to.have.length( 6 );
 			expect( tpl.children[ 0 ].text[ 0 ] ).to.equal( 'content' );
 			expect( tpl.children[ 1 ].text[ 0 ] ).to.be.instanceof( TemplateToBinding );
 			expect( tpl.children[ 2 ].text[ 0 ] ).to.equal( 'abc' );
 			expect( tpl.children[ 3 ].text[ 0 ] ).to.equal( 'a' );
 			expect( tpl.children[ 3 ].text[ 1 ] ).to.equal( 'b' );
+			expect( tpl.children[ 4 ] ).to.equal( childNode );
+			expect( tpl.children[ 5 ] ).to.equal( childTemplate );
 
 			expect( tpl.eventListeners[ 'a@span' ][ 0 ] ).to.be.instanceof( TemplateToBinding );
 			expect( tpl.eventListeners[ 'b@span' ][ 0 ] ).to.be.instanceof( TemplateToBinding );
@@ -514,6 +523,38 @@ describe( 'Template', () => {
 				expect( collection._parentElement ).to.equal( rendered );
 			} );
 
+			it( 'renders DOM nodes', () => {
+				const view = new View();
+
+				view.set( {
+					foo: 'bar',
+					bar: 'baz'
+				} );
+
+				const bind = Template.bind( view, view );
+
+				const childA = new Template( {
+					tag: 'b',
+					attributes: {
+						class: bind.to( 'foo' )
+					}
+				} ).render();
+
+				const childB = new Template( {
+					text: bind.to( 'bar' )
+				} ).render();
+
+				const rendered = new Template( {
+					tag: 'p',
+					children: [
+						childA,
+						childB
+					]
+				} ).render();
+
+				expect( normalizeHtml( rendered.outerHTML ) ).to.equal( '<p><b class="bar"></b>baz</p>' );
+			} );
+
 			// #117
 			it( 'renders template children', () => {
 				const childTplA = new Template( {