From 7602f36c7ff0d191caa5a87487f8aefde2836f3d Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Thu, 19 Jan 2017 10:40:15 -0600 Subject: [PATCH 01/11] Don't error when dom doesn't exist yet --- src/strand-form/strand-form.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/strand-form/strand-form.js b/src/strand-form/strand-form.js index edb013be..ae32ae3b 100644 --- a/src/strand-form/strand-form.js +++ b/src/strand-form/strand-form.js @@ -402,8 +402,11 @@ } // show or hide messaging in the ui - errorMsgEleDOM.message = errorMsg; - field.error = errorMsgEleDOM.visible = !valid; + // 'pre-set' values can kick off validation + if (errorMsgEleDOM && field) { + errorMsgEleDOM.message = errorMsg; + field.error = errorMsgEleDOM.visible = !valid; + } return valid; }, From dac4c557a32ff8786bff0b7f84a730c7f7d3ec3b Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Thu, 19 Jan 2017 13:01:47 -0600 Subject: [PATCH 02/11] Handle initial form values more gracefully --- src/strand-form/strand-form.js | 77 ++++++++++++------- .../strand-test-form-view.html | 18 ++--- .../strand-test-form-view.js | 2 +- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/strand-form/strand-form.js b/src/strand-form/strand-form.js index ae32ae3b..3fd4e91e 100644 --- a/src/strand-form/strand-form.js +++ b/src/strand-form/strand-form.js @@ -101,6 +101,18 @@ type: Boolean, computed: '_displayMessage(_showFooterMessage, showFooterMessages)' }, + _dataInitialized: { + type: Boolean, + value: false + }, + _configInitialized: { + type: Boolean, + value: false + }, + _initialized: { + type: Boolean, + computed: '_computeInitalized(_dataInitialized, _configInitialized)' + }, // config/initial data & settings: config: { type: Object, @@ -111,7 +123,7 @@ type: Object, observer: '_dataChanged', value: function() { return {}; } - } + }, }, _initialData: {}, @@ -135,12 +147,14 @@ _dataChanged: function(newVal, oldVal) { if(!this._isEmpty(newVal)) { this.debounce('initData', this._initData); + this._dataInitialized = false; } }, _configChanged: function(newVal, oldVal) { if (!this._isEmpty(newVal)) { this.debounce('initConfig', this._initConfig); + this._configInitialized = false; } }, @@ -205,6 +219,8 @@ this._createLabel(key, cfg[key].label, field, cfg[key].parentEleDOM); } } + + this._configInitialized = true; }, _initData: function() { @@ -234,6 +250,12 @@ field.value = value; } } + + this._dataInitialized = true; + }, + + _computeInitalized: function(_dataInitialized, _configInitialized) { + return _dataInitialized && _configInitialized; }, _createErrorMsg:function(key, errorMsg, parentEleDOM) { @@ -284,30 +306,32 @@ // handle changes within the form _handleChanged: function(e) { - var field = e.target; - var key = field.getAttribute('name'); - var value = null; - var validation = null; - var exclude = null; - var isFormElement = this.config.hasOwnProperty(key); - - if (isFormElement) { - exclude = this.config[key].exclude ? this.config[key].exclude : false; - value = e.detail.value; - validation = this.config[key].validation; - - if (!exclude) { - this._updateData(key, value); - this._setUnsaved(this._diffData()); - } + if (this._initialized) { + var field = e.target; + var key = field.getAttribute('name'); + var value = null; + var validation = null; + var exclude = null; + var isFormElement = this.config.hasOwnProperty(key); + + if (isFormElement) { + exclude = this.config[key].exclude ? this.config[key].exclude : false; + value = e.detail.value; + validation = this.config[key].validation; + + if (!exclude) { + this._updateData(key, value); + this._setUnsaved(this._diffData()); + } - if (validation && this.autoValidate) this._validateField(key, value); + if (validation && this.autoValidate) this._validateField(key, value); - // show messaging in the footer - if (this.unsaved && this.showUnsavedMessage) { - this._handleFooter(this.footerMessages.warning, 'warning', true); - } else { - this._showFooterMessage = false; + // show messaging in the footer + if (this.unsaved && this.showUnsavedMessage) { + this._handleFooter(this.footerMessages.warning, 'warning', true); + } else { + this._showFooterMessage = false; + } } } }, @@ -402,11 +426,8 @@ } // show or hide messaging in the ui - // 'pre-set' values can kick off validation - if (errorMsgEleDOM && field) { - errorMsgEleDOM.message = errorMsg; - field.error = errorMsgEleDOM.visible = !valid; - } + errorMsgEleDOM.message = errorMsg; + field.error = errorMsgEleDOM.visible = !valid; return valid; }, diff --git a/src/strand-test-form-view/strand-test-form-view.html b/src/strand-test-form-view/strand-test-form-view.html index a8ffc92b..ffbb0407 100644 --- a/src/strand-test-form-view/strand-test-form-view.html +++ b/src/strand-test-form-view/strand-test-form-view.html @@ -31,23 +31,23 @@
- - List Item 1 - List Item 2 - List Item 3 - List Item 4 + + List Item 1 + List Item 2 + List Item 3 + List Item 4
- - + + - + - + diff --git a/src/strand-test-form-view/strand-test-form-view.js b/src/strand-test-form-view/strand-test-form-view.js index c4e3ecc2..b9416468 100644 --- a/src/strand-test-form-view/strand-test-form-view.js +++ b/src/strand-test-form-view/strand-test-form-view.js @@ -59,7 +59,7 @@ }, 'radio' : { validation: function(name, value, data, view) { - return data[name] === 'Red' && value === 'Red'; + return data[name] === '1' && value === '1'; }, errorMsg: 'You need to select \'Red\'', label: 'Select a Color' From a699144e3a6f05df9880da96440ba0931e2a8a82 Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Mon, 23 Jan 2017 15:37:10 -0600 Subject: [PATCH 03/11] Better reuse of DOM when changing data or config --- src/strand-form/strand-form.js | 104 ++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/src/strand-form/strand-form.js b/src/strand-form/strand-form.js index 3fd4e91e..6b9e44b1 100644 --- a/src/strand-form/strand-form.js +++ b/src/strand-form/strand-form.js @@ -101,6 +101,7 @@ type: Boolean, computed: '_displayMessage(_showFooterMessage, showFooterMessages)' }, + // config/initial data & settings: _dataInitialized: { type: Boolean, value: false @@ -113,7 +114,6 @@ type: Boolean, computed: '_computeInitalized(_dataInitialized, _configInitialized)' }, - // config/initial data & settings: config: { type: Object, observer: '_configChanged', @@ -184,6 +184,8 @@ validation: attrs.validation || null, noValidate: null, label: attrs.label || null, + labelEle: attrs['label-ele'] || null, + labelEleDOM: this._select('#'+attrs['label-ele']) || null, errorMsg: attrs['error-msg'] || null, errorMsgEle: attrs['error-msg-ele'] || null, errorMsgEleDOM: this._select('#'+attrs['error-msg-ele']) || null, @@ -202,24 +204,35 @@ for (var key in config) { var field = config[key].field || this._select('[name='+key+']'); var cfg = config; + var existingLblEle = this._select('._'+key+'-label') || null; + var existingMsgEle = this._select('._'+key+'-error-msg') || null; + if (!field) throw 'There must be a corresponding DOM element for config[\''+key+'\']'; cfg[key] = StrandLib.DataUtils.copy(domConfig[key], cfg[key]); - cfg[key].errorMsgEleDOM = this._select('#'+cfg[key].errorMsgEle) || null; + cfg[key].errorMsgEleDOM = this._select('#'+cfg[key].errorMsgEle) || existingMsgEle; + cfg[key].labelEleDOM = this._select('#'+cfg[key].labelEle) || existingLblEle; cfg[key].parentEleDOM = this._select('#'+cfg[key].parentEle) || Polymer.dom(field).parentNode; // Create error message element (if one was not specified already) - if (cfg[key].errorMsg && !cfg[key].errorMsgEleDOM) { + // or update the dev provided / existing error msg element: + if (cfg[key].errorMsg && !existingMsgEle && !cfg[key].errorMsgEleDOM) { this._createErrorMsg(key, cfg[key].errorMsg, cfg[key].parentEleDOM); + } else if (cfg[key].errorMsg && cfg[key].errorMsgEleDOM) { + this._updateErrorMsg(key, cfg[key].errorMsg, cfg[key].errorMsgEleDOM); } - // Create the field label - if (cfg[key].label) { + // Create or update label (same as errorMsg) + if (cfg[key].label && !existingLblEle && !cfg[key].labelEleDOM) { this._createLabel(key, cfg[key].label, field, cfg[key].parentEleDOM); + } else if (cfg[key].label && cfg[key].labelEleDOM) { + this._updateLabel(key, cfg[key].label, cfg[key].labelEleDOM); } } + this.clearValidationState(); + this.clearFooterMsg(); this._configInitialized = true; }, @@ -251,6 +264,8 @@ } } + this.clearValidationState(); + this.clearFooterMsg(); this._dataInitialized = true; }, @@ -259,48 +274,43 @@ }, _createErrorMsg:function(key, errorMsg, parentEleDOM) { - var existingMsgEle = this._select('._'+key+'-error-msg') || null; + errorMsgEleDOM = new Strand.FormMessage(); + errorMsgEleDOM.type = 'error'; - if (!existingMsgEle) { - // create one: - errorMsgEleDOM = new Strand.FormMessage(); - errorMsgEleDOM.type = 'error'; + errorMsgEleDOM.message = errorMsg; + errorMsgEleDOM.classList.add('_'+key+'-error-msg'); + Polymer.dom(parentEleDOM).appendChild(errorMsgEleDOM); - errorMsgEleDOM.message = errorMsg; - errorMsgEleDOM.classList.add('_'+key+'-error-msg'); - Polymer.dom(parentEleDOM).appendChild(errorMsgEleDOM); + this.config[key].errorMsgEleDOM = errorMsgEleDOM; + }, - this.config[key].errorMsgEleDOM = errorMsgEleDOM; - } else { - existingMsgEle.message = errorMsg; - - this.config[key].errorMsgEleDOM = existingMsgEle; - } + _updateErrorMsg:function(key, errorMsg, errorMsgEleDOM) { + if (errorMsgEleDOM) errorMsgEleDOM.message = errorMsg; }, _createLabel:function(key, label, field, parentEleDOM) { - var existingLblEle = this._select('._'+key+'-label') || null; - var labelTxt = document.createTextNode(label); - var formLabel = null; + var labelTxt = document.createTextNode(label); + var labelEleDOM = null; + + labelEleDOM = new Strand.Header(); + labelEleDOM.size = 'medium'; + labelEleDOM.setAttribute('name', name); + labelEleDOM.classList.add('_'+key+'-label'); + // TODO: strand-form-header element(?) + labelEleDOM.setAttribute('form-header', true); - if (!existingLblEle) { - // create a new label - formLabel = new Strand.Header(); + Polymer.dom(labelEleDOM).appendChild(labelTxt); + Polymer.dom(parentEleDOM).insertBefore(labelEleDOM, field); - formLabel.size = 'medium'; - formLabel.setAttribute('name', name); - formLabel.classList.add('_'+key+'-label'); - formLabel.setAttribute('form-header', true); + this.config[key].labelEleDOM = labelEleDOM; + }, - Polymer.dom(formLabel).appendChild(labelTxt); - Polymer.dom(parentEleDOM).insertBefore(formLabel, field); + _updateLabel: function(key, label, labelEleDOM) { + if (labelEleDOM) { + var labelTxt = document.createTextNode(label); - this.config[key].formLabel = formLabel; - } else { - Polymer.dom(existingLblEle).textContent = null; - Polymer.dom(existingLblEle).appendChild(labelTxt); - - this.config[key].formLabel = existingLblEle; + Polymer.dom(labelEleDOM).textContent = null; + Polymer.dom(labelEleDOM).appendChild(labelTxt); } }, @@ -426,8 +436,13 @@ } // show or hide messaging in the ui - errorMsgEleDOM.message = errorMsg; - field.error = errorMsgEleDOM.visible = !valid; + // it is possible that there may not be an errorMsgEleDOM + if (errorMsgEleDOM) { + errorMsgEleDOM.message = errorMsg; + errorMsgEleDOM.visible = !valid; + } + + field.error = !valid; return valid; }, @@ -475,7 +490,18 @@ this.fire('cancel-form'); }, + // TODO: public - needs doc + clearValidationState: function() { + for (var key in this.config) { + this.resetFieldValidation(key); + } + }, + // footer and footer actions: + clearFooterMsg: function() { + this._handleFooter(undefined, undefined, false); + }, + _validType: function(type) { return type === 'primary' || type === 'secondary'; }, From 32413f2246d2e3bc7fdf5c3394bbd11718928254 Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Mon, 23 Jan 2017 15:50:48 -0600 Subject: [PATCH 04/11] Fix test for labels --- test/strand-form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/strand-form.html b/test/strand-form.html index b112b79e..51daac97 100644 --- a/test/strand-form.html +++ b/test/strand-form.html @@ -153,7 +153,7 @@ var objLength = Object.keys(config).length; for (var item in config) { - labels.push(config[item].formLabel); + labels.push(config[item].labelEleDOM); } labels[0].should.exist; From a48d1450fcf59a7cd019b2f45e609ec0246cec63 Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Mon, 23 Jan 2017 17:42:14 -0600 Subject: [PATCH 05/11] WIP document and test --- src/strand-form/index.html | 19 +++++++++++++++---- test/strand-form.html | 30 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/strand-form/index.html b/src/strand-form/index.html index 136da613..d25eda77 100644 --- a/src/strand-form/index.html +++ b/src/strand-form/index.html @@ -36,6 +36,7 @@ +
@@ -85,10 +86,15 @@
+ - + --> From 429c6d96768b07cdffeebbd720ed0a5f0b8162c2 Mon Sep 17 00:00:00 2001 From: Anthony Koerber Date: Thu, 26 Jan 2017 11:49:03 -0600 Subject: [PATCH 11/11] fix test --- test/strand-form.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/strand-form.html b/test/strand-form.html index 8d1fddd5..348aeeb2 100644 --- a/test/strand-form.html +++ b/test/strand-form.html @@ -106,7 +106,7 @@