瀏覽代碼

Merge pull request #46 from ckeditor/t/ckeditor5-ui-default/25

Allowed ObservableMixin bindings to attributes which don't exist (yet).
Piotrek Koszuliński 9 年之前
父節點
當前提交
d6b4aebe10

+ 0 - 20
packages/ckeditor5-utils/src/observablemixin.js

@@ -396,16 +396,6 @@ function bindTo( ...args ) {
 		if ( !to.attrs.length ) {
 			to.attrs = this._bindAttrs;
 		}
-
-		// Eliminate A.bind( 'x', 'y' ).to( B, 'a', 'b' ) when B has no 'a'.
-		if ( !hasAttributes( to.observable, to.attrs ) ) {
-			/*
-			 * Observable has no such attribute(s).
-			 *
-			 * @error observable-bind-to-missing-attr
-			 */
-			throw new CKEditorError( 'observable-bind-to-missing-attr: Observable has no such attribute(s).' );
-		}
 	} );
 
 	this._to = parsedArgs.to;
@@ -426,16 +416,6 @@ function bindTo( ...args ) {
 	} );
 }
 
-// Check if the {@link utils.Observable} has given `attrs`.
-//
-// @private
-// @param {Observable} observable Observable to be checked.
-// @param {Array} arr An array of `String`.
-// @returns {Boolean}
-function hasAttributes( observable, attrs ) {
-	return attrs.every( a => observable[ attributesSymbol ].has( a ) );
-}
-
 // Check if all entries of the array are of `String` type.
 //
 // @private

+ 8 - 4
packages/ckeditor5-utils/tests/_utils/utils.js

@@ -65,16 +65,20 @@ const utils = {
 	 *		);
 	 */
 	assertBinding( observable, stateBefore, data, stateAfter ) {
-		let key, pair;
+		let key, boundObservable, attrs;
 
 		for ( key in stateBefore ) {
 			expect( observable[ key ] ).to.be.equal( stateBefore[ key ] );
 		}
 
 		// Change attributes of bound observables.
-		for ( pair of data ) {
-			for ( key in pair[ 1 ] ) {
-				pair[ 0 ][ key ] = pair[ 1 ][ key ];
+		for ( [ boundObservable, attrs ] of data ) {
+			for ( key in attrs ) {
+				if ( !boundObservable.hasOwnProperty( key ) ) {
+					boundObservable.set( key, attrs[ key ] );
+				} else {
+					boundObservable[ key ] = attrs[ key ];
+				}
 			}
 		}
 

+ 36 - 10
packages/ckeditor5-utils/tests/observablemixin.js

@@ -327,20 +327,46 @@ describe( 'Observable', () => {
 				} ).to.throw( CKEditorError, /observable-bind-to-attrs-length/ );
 			} );
 
-			it( 'should throw when attributes don\'t exist in to() observable', () => {
+			it( 'should work when attributes don\'t exist in to() observable #1', () => {
 				const vehicle = new Car();
 
-				expect( () => {
-					vehicle.bind( 'color' ).to( car, 'nonexistent in car' );
-				} ).to.throw( CKEditorError, /observable-bind-to-missing-attr/ );
+				vehicle.bind( 'color' ).to( car, 'nonexistent in car' );
 
-				expect( () => {
-					vehicle.bind( 'nonexistent in car' ).to( car );
-				} ).to.throw( CKEditorError, /observable-bind-to-missing-attr/ );
+				assertBinding( vehicle,
+					{ color: undefined, year: undefined },
+					[
+						[ car, { 'nonexistent in car': 'foo', year: 1969 } ]
+					],
+					{ color: 'foo', year: undefined }
+				);
+			} );
 
-				expect( () => {
-					vehicle.bind( 'year' ).to( car, 'color', car, 'nonexistent in car', () => {} );
-				} ).to.throw( CKEditorError, /observable-bind-to-missing-attr/ );
+			it( 'should work when attributes don\'t exist in to() observable #2', () => {
+				const vehicle = new Car();
+
+				vehicle.bind( 'nonexistent in car' ).to( car );
+
+				assertBinding( vehicle,
+					{ 'nonexistent in car': undefined, year: undefined },
+					[
+						[ car, { 'nonexistent in car': 'foo', year: 1969 } ]
+					],
+					{ 'nonexistent in car': 'foo', year: undefined }
+				);
+			} );
+
+			it( 'should work when attributes don\'t exist in to() observable #3', () => {
+				const vehicle = new Car();
+
+				vehicle.bind( 'year' ).to( car, 'color', car, 'nonexistent in car', ( a, b ) => a + b );
+
+				assertBinding( vehicle,
+					{ color: undefined, year: car.color + undefined },
+					[
+						[ car, { color: 'blue', year: 1969 } ]
+					],
+					{ color: undefined, year: 'blueundefined' }
+				);
 			} );
 
 			it( 'should set new observable attributes', () => {