diff --git a/src/WidgetBase.ts b/src/WidgetBase.ts index 8e3a0914..538b79b6 100644 --- a/src/WidgetBase.ts +++ b/src/WidgetBase.ts @@ -7,6 +7,7 @@ import { isWNode, v, isHNode } from './d'; import { auto, ignore } from './diff'; import { AfterRender, + BeforeProperties, BeforeRender, CoreProperties, DiffPropertyFunction, @@ -361,7 +362,8 @@ export class WidgetBase
extends E this._coreProperties = coreProperties; } - public __setProperties__(properties: this['properties']): void { + public __setProperties__(originalProperties: this['properties']): void { + const properties = this._runBeforeProperties(originalProperties); const changedPropertyKeys: string[] = []; const allProperties = [ ...Object.keys(properties), ...Object.keys(this._properties) ]; const checkedProperties: string[] = []; @@ -378,7 +380,7 @@ export class WidgetBase
extends E } checkedProperties.push(propertyName); const previousProperty = this._properties[propertyName]; - const newProperty = this._bindFunctionProperty((properties as any)[propertyName], this._coreProperties.bind); + const newProperty = this._bindFunctionProperty(properties[propertyName], this._coreProperties.bind); if (registeredDiffPropertyNames.indexOf(propertyName) !== -1) { runReactions = true; const diffFunctions = this.getDecorator(`diffProperty:${propertyName}`); @@ -633,6 +635,16 @@ export class WidgetBase
extends E return this._registries; } + private _runBeforeProperties(properties: any) { + const beforeProperties: BeforeProperties[] = this.getDecorator('beforeProperties'); + if (beforeProperties.length > 0) { + return beforeProperties.reduce((properties, beforePropertiesFunction) => { + return { ...properties, ...beforePropertiesFunction(properties) }; + }, { ...properties }); + } + return properties; + } + /** * Run all registered before renders and return the updated render method */ diff --git a/src/decorators/beforeProperties.ts b/src/decorators/beforeProperties.ts new file mode 100644 index 00000000..4561d450 --- /dev/null +++ b/src/decorators/beforeProperties.ts @@ -0,0 +1,16 @@ +import { handleDecorator } from './../WidgetBase'; +import { BeforeProperties } from './../interfaces'; + +/** + * Decorator that adds the function passed of target method to be run + * in the `beforeProperties` lifecycle. + */ +export function beforeProperties(method: BeforeProperties): (target: any) => void; +export function beforeProperties(): (target: any, propertyKey: string) => void; +export function beforeProperties(method?: BeforeProperties) { + return handleDecorator((target, propertyKey) => { + target.addDecorator('beforeProperties', propertyKey ? target[propertyKey] : method); + }); +} + +export default beforeProperties; diff --git a/src/interfaces.d.ts b/src/interfaces.d.ts index c72ce8a5..66f514d7 100644 --- a/src/interfaces.d.ts +++ b/src/interfaces.d.ts @@ -442,3 +442,10 @@ export interface BeforeRender { export interface AfterRender { (dNode: DNode | DNode []): DNode | DNode[]; } + +/** + * Interface for beforeProperties function + */ +export interface BeforeProperties
{
+ (properties: P): P;
+}
diff --git a/tests/unit/all.ts b/tests/unit/all.ts
index 3c558758..d7acfc6e 100644
--- a/tests/unit/all.ts
+++ b/tests/unit/all.ts
@@ -5,6 +5,7 @@ import './WidgetRegistry';
import './lifecycle';
import './customElements';
import './d';
+import './decorators/all';
import './mixins/all';
import './util/all';
import './main';
diff --git a/tests/unit/decorators/all.ts b/tests/unit/decorators/all.ts
new file mode 100644
index 00000000..f8ac3f2d
--- /dev/null
+++ b/tests/unit/decorators/all.ts
@@ -0,0 +1 @@
+import './beforeProperties';
diff --git a/tests/unit/decorators/beforeProperties.ts b/tests/unit/decorators/beforeProperties.ts
new file mode 100644
index 00000000..fca8923d
--- /dev/null
+++ b/tests/unit/decorators/beforeProperties.ts
@@ -0,0 +1,69 @@
+import * as registerSuite from 'intern!object';
+import * as assert from 'intern/chai!assert';
+
+import { beforeProperties } from './../../../src/decorators/beforeProperties';
+import { WidgetBase } from './../../../src/WidgetBase';
+import { WidgetProperties } from './../../../src/interfaces';
+
+registerSuite({
+ name: 'decorators/beforeProperties',
+ beforeProperties() {
+ function before(properties: WidgetProperties): WidgetProperties {
+ return { key: 'foo' };
+ }
+
+ @beforeProperties(before)
+ class TestWidget extends WidgetBase