Procházet zdrojové kódy

Fixed: Double Template rendering if the View instance belongs to children of another Template.

Aleksander Nowodzinski před 9 roky
rodič
revize
430d776c48

+ 23 - 9
packages/ckeditor5-ui/src/template.js

@@ -510,12 +510,21 @@ export default class Template {
 	 */
 	_renderElementChildren( elOrDocFragment, shouldApply ) {
 		let childIndex = 0;
+		let tpl, rendered;
+
+		for ( let child of this.children ) {
+			tpl = isView( child ) ? child.template : child;
 
-		for ( let template of this.children ) {
 			if ( shouldApply ) {
-				template._renderNode( elOrDocFragment.childNodes[ childIndex++ ] );
+				rendered = tpl._renderNode( elOrDocFragment.childNodes[ childIndex++ ] );
 			} else {
-				elOrDocFragment.appendChild( template.render() );
+				elOrDocFragment.appendChild( ( rendered = tpl.render() ) );
+			}
+
+			// Set the element of the view the template belongs to to avoid re–rendering
+			// when the element later on by the view.
+			if ( isView( child ) ) {
+				child.element = rendered;
 			}
 		}
 	}
@@ -842,7 +851,7 @@ function clone( def ) {
 		// Also don't clone View instances if provided as a child of the Template. The template
 		// instance will be extracted from the View during the normalization and there's no need
 		// to clone it.
-		if ( value && ( value instanceof TemplateBinding || value instanceof View ) ) {
+		if ( value && ( value instanceof TemplateBinding || isView( value ) ) ) {
 			return value;
 		}
 	} );
@@ -883,11 +892,7 @@ function normalize( def ) {
 
 		if ( def.children ) {
 			for ( let child of def.children ) {
-				if ( child instanceof View ) {
-					children.add( child.template );
-				} else {
-					children.add( new Template( child ) );
-				}
+				children.add( isView( child ) ? child : new Template( child ) );
 			}
 		}
 
@@ -1100,11 +1105,20 @@ function extendTemplate( template, def ) {
 // Checks if value is "falsy".
 // Note: 0 (Number) is not "falsy" in this context.
 //
+// @private
 // @param {*} value Value to be checked.
 function isFalsy( value ) {
 	return !value && value !== 0;
 }
 
+// Checks if the item is an instance of {@link ui.View}
+//
+// @private
+// @param {*} value Value to be checked.
+function isView( item ) {
+	return item instanceof View;
+}
+
 /**
  * A definition of {@link ui.Template}.
  * See: {@link ui.TemplateValueSchema}.

+ 11 - 3
packages/ckeditor5-ui/tests/template.js

@@ -432,9 +432,17 @@ describe( 'Template', () => {
 					children: [ v1, v2 ]
 				} );
 
-				expect( tpl.children.get( 0 ) ).to.equal( v1.template );
-				expect( tpl.children.get( 1 ) ).to.equal( v2.template );
-				expect( normalizeHtml( tpl.render().outerHTML ) ).to.equal( '<p><span class="v1"></span><span class="v2"></span></p>' );
+				expect( tpl.children.get( 0 ) ).to.equal( v1 );
+				expect( tpl.children.get( 1 ) ).to.equal( v2 );
+
+				const rendered = tpl.render();
+
+				expect( normalizeHtml( rendered.outerHTML ) ).to.equal( '<p><span class="v1"></span><span class="v2"></span></p>' );
+
+				// Make sure the child views will not re–render their elements but
+				// use ones rendered by the template instance above.
+				expect( v1.element ).to.equal( rendered.firstChild );
+				expect( v2.element ).to.equal( rendered.lastChild );
 			} );
 		} );