Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

add beforeProperties lifecycle hook #663

Merged
merged 2 commits into from
Sep 6, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/WidgetBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { isWNode, v, isHNode } from './d';
import { auto, ignore } from './diff';
import {
AfterRender,
BeforeProperties,
BeforeRender,
CoreProperties,
DiffPropertyFunction,
Expand Down Expand Up @@ -361,7 +362,8 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> 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[] = [];
Expand All @@ -378,7 +380,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> 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}`);
Expand Down Expand Up @@ -633,6 +635,16 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> 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
*/
Expand Down
15 changes: 15 additions & 0 deletions src/decorators/beforeProperties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { handleDecorator } from './../WidgetBase';
import { BeforeProperties } from './../interfaces';

/**
*
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc please

*/
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;
7 changes: 7 additions & 0 deletions src/interfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,10 @@ export interface BeforeRender {
export interface AfterRender {
(dNode: DNode | DNode []): DNode | DNode[];
}

/**
* Interface for beforeProperties function
*/
export interface BeforeProperties<P = any> {
(properties: P): P;
}
1 change: 1 addition & 0 deletions tests/unit/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import './WidgetRegistry';
import './lifecycle';
import './customElements';
import './d';
import './decorators/all';
import './mixins/all';
import './util/all';
import './main';
Expand Down
1 change: 1 addition & 0 deletions tests/unit/decorators/all.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './beforeProperties';
69 changes: 69 additions & 0 deletions tests/unit/decorators/beforeProperties.ts
Original file line number Diff line number Diff line change
@@ -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<any> {}
const widget = new TestWidget();
widget.__setProperties__({});
assert.strictEqual(widget.properties.key, 'foo');
},
'multiple beforeProperties decorators'() {
function beforeOne(properties: WidgetProperties): WidgetProperties {
return { key: 'foo' };
}
function beforeTwo(properties: any): any {
return { other: 'bar' };
}

@beforeProperties(beforeOne)
@beforeProperties(beforeTwo)
class TestWidget extends WidgetBase<any> {}
const widget = new TestWidget();
widget.__setProperties__({});
assert.strictEqual(widget.properties.key, 'foo');
assert.strictEqual(widget.properties.other, 'bar');
},
'beforeProperties on class method'() {
class TestWidget extends WidgetBase<any> {
@beforeProperties()
before(properties: WidgetProperties): WidgetProperties {
return { key: 'foo' };
}
}
const widget = new TestWidget();
widget.__setProperties__({});
assert.strictEqual(widget.properties.key, 'foo');

},
'programmatic beforeProperties'() {
function beforeOne(properties: WidgetProperties): WidgetProperties {
return { key: 'foo' };
}
function beforeTwo(properties: any): any {
return { other: 'bar' };
}

class TestWidget extends WidgetBase<any> {
constructor() {
super();
beforeProperties(beforeOne)(this);
beforeProperties(beforeTwo)(this);
}
}
const widget = new TestWidget();
widget.__setProperties__({});
assert.strictEqual(widget.properties.key, 'foo');
assert.strictEqual(widget.properties.other, 'bar');
}
});