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

Commit

Permalink
add beforeProperties lifecycle hook (#663)
Browse files Browse the repository at this point in the history
* add beforeProperties lifecycle hook

* doc
  • Loading branch information
agubler authored Sep 6, 2017
1 parent 5084533 commit a71d937
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 2 deletions.
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
16 changes: 16 additions & 0 deletions src/decorators/beforeProperties.ts
Original file line number Diff line number Diff line change
@@ -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;
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');
}
});

0 comments on commit a71d937

Please sign in to comment.