From d56af56bc5b1dc857ef55bc08ecbc63dd803d8f1 Mon Sep 17 00:00:00 2001 From: "Noj Vek (Manoj P)" Date: Mon, 10 Sep 2018 16:39:41 -0700 Subject: [PATCH] _syncAttrs on constructor and connectedCallback (#43) * _syncAttrs on constructor and connectedCallback * Tests * spelling * remove _syncAttrs on connectedCallback * fix server test --- lib/component.js | 17 +++++++++++++++-- test/browser/component.js | 12 ++++++++++++ test/fixtures/attrs-reflection-app.js | 3 +++ test/server/component.js | 3 +-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/component.js b/lib/component.js index cce0ff85..8914ffe2 100644 --- a/lib/component.js +++ b/lib/component.js @@ -201,6 +201,10 @@ class Component extends WebComponent { super(); this.panelID = cuid(); + + this.attrs = {}; + this._syncAttrs(); // constructor sync ensures default properties are present on this.attrs + this._config = Object.assign({}, { css: ``, helpers: {}, @@ -214,8 +218,8 @@ class Component extends WebComponent { // appState and isStateShared of child components will be overwritten by parent/root // when the component is connected to the hierarchy this.state = {}; - this.attrs = {}; this.appState = this.getConfig(`appState`); + if (!this.appState) { this.appState = {}; this.isStateShared = true; @@ -288,7 +292,6 @@ class Component extends WebComponent { ); Object.assign(this.state, newState); - Object.keys(this.constructor.attrsSchema).forEach(attr => this._updateAttr(attr)); if (Object.keys(this.getConfig(`routes`)).length) { this.router = new Router(this, {historyMethod: this.historyMethod}); @@ -420,6 +423,16 @@ class Component extends WebComponent { return state; } + /** + * Syncs element attributes defined in attrsSchema with this.attrs + */ + _syncAttrs() { + for (const attr of Object.keys(this.constructor.attrsSchema)) { + this._updateAttr(attr); + } + return this.attrs; + } + /** * Parses html attribute using type information from attrsSchema and updates this.attrs * @param {string} attr - attribute name diff --git a/test/browser/component.js b/test/browser/component.js index fd6d4d90..298eae36 100644 --- a/test/browser/component.js +++ b/test/browser/component.js @@ -265,6 +265,18 @@ describe(`Simple Component instance with attrsSchema`, function() { `json-attr`, ]); }); + + it(`has default attrs present after createElement`, function() { + el = document.createElement(`attrs-reflection-app`); + expect(el.attrs).to.deep.equal({ + 'str-attr': `placeholder`, + 'bool-attr': false, + 'number-attr': 0, + 'json-attr': null, + }); + // _config is initialised in constructor. defaultState should be able to access el.attrs + expect(el._config.defaultState.str).to.equal(`placeholder`); + }); }); describe(`Nested Component instance`, function() { diff --git a/test/fixtures/attrs-reflection-app.js b/test/fixtures/attrs-reflection-app.js index ece9790b..e82afcd2 100644 --- a/test/fixtures/attrs-reflection-app.js +++ b/test/fixtures/attrs-reflection-app.js @@ -14,6 +14,9 @@ export class AttrsReflectionApp extends Component { template: scope => h(`div`, {class: {'attrs-reflection-app': true}}, Object.entries(scope.$attrs).map(([attr, val]) => h(`p`, `${attr}: ${JSON.stringify(val)}`)), ), + defaultState: { + str: this.attrs[`str-attr`], + }, }; } } diff --git a/test/server/component.js b/test/server/component.js index 2ffc46b5..ffb52453 100644 --- a/test/server/component.js +++ b/test/server/component.js @@ -178,8 +178,7 @@ describe(`Server-side component renderer`, function() { }); it(`throws error if there is a malformed attrsSchema type`, function() { - const el = new BadAttrsSchemaApp(); - expect(() => el.connectedCallback()).to.throw( + expect(() => new BadAttrsSchemaApp()).to.throw( `Unknown type: bool for attr: bad-attr in attrsSchema. Only (string | boolean | number | json) supported.` ); });