Skip to content

Commit 34ba4eb

Browse files
Exploration of validate if logic working via config
1 parent 56becea commit 34ba4eb

4 files changed

Lines changed: 166 additions & 110 deletions

File tree

src/mm-form/mm-form.js

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
],
1919

2020
properties: {
21+
view: {
22+
type: Object
23+
},
2124
unsaved: {
2225
type: Boolean,
2326
value: true,
@@ -82,6 +85,7 @@
8285
type: Boolean,
8386
computed: '_displayMessage(_showFooterMessage, showFooterMessages)'
8487
},
88+
8589
// config/initial data & settings:
8690
config: {
8791
type: Object,
@@ -90,7 +94,8 @@
9094
},
9195
data: {
9296
type: Object,
93-
observer: '_dataChanged'
97+
observer: '_dataChanged',
98+
value: function() { return {}; }
9499
}
95100
},
96101

@@ -104,66 +109,60 @@
104109

105110
_dataChanged: function(newVal, oldVal) {
106111
console.log('_dataChanged:', newVal);
107-
this.debounce('init', this._initForm);
112+
// this.debounce('init', this._initForm);
113+
this._initData();
108114
},
109115

110116
_configChanged: function(newVal, oldVal) {
111117
console.log('_configChanged:', newVal);
112-
this.debounce('init', this._initForm);
118+
// this.debounce('init', this._initForm);
119+
this._initConfig();
113120
},
114121

115-
_selectEle: function(ele, parent) {
122+
_select: function(ele, parent) {
116123
var scope = this || parent;
117124
return Polymer.dom(scope).querySelector(ele);
118125
},
119126

120-
_initForm: function() {
121-
if (!this.data) return;
122-
123-
for (var key in this.data) {
124-
var cfgKey = this.config[key] ? this.config[key] : null,
125-
field = this._selectEle('[name='+key+']'),
126-
validation = null,
127-
label = null,
128-
errorMsg = null,
129-
errorMsgEle = null,
130-
parentEle = null,
131-
value = this.data[key] || null;
127+
_initConfig: function() {
128+
for (var key in this.config) {
129+
var cfg = this.config[key] ? this.config[key] : null,
130+
field = this._select('[name='+key+']'),
131+
validation = null,
132+
validateIf = null,
133+
label = null,
134+
errorMsg = null,
135+
errorMsgEle = null,
136+
parentEle = null;
132137

133138
if (!field) {
134-
throw 'There must be a corresponding DOM element for data[\''+key+'\']';
139+
throw 'There must be a corresponding DOM element for config[\''+key+'\']';
135140
}
136141

137142
// a config was or was not supplied - if one was supplied,
138143
// use it, if not create one
139-
if (cfgKey) {
140-
validation = cfgKey.validation ? cfgKey.validation : null,
141-
label = cfgKey.label ? cfgKey.label : null,
142-
errorMsg = cfgKey.errorMsg ? cfgKey.errorMsg : null,
143-
errorMsgEle = cfgKey.errorMsgEle ? this._selectEle('#'+cfgKey.errorMsgEle) : null,
144-
parentEle = cfgKey.parentEle ? this._selectEle('#'+cfgKey.parentEle) : Polymer.dom(field).parentNode;
144+
if (cfg) {
145+
validation = cfg.validation ? cfg.validation : null;
146+
validateIf = cfg.validateIf ? cfg.validateIf : null;
147+
label = cfg.label ? cfg.label : null;
148+
errorMsg = cfg.errorMsg ? cfg.errorMsg : null;
149+
errorMsgEle = cfg.errorMsgEle ? this._select('#'+cfg.errorMsgEle) : null;
150+
parentEle = cfg.parentEle ? this._select('#'+cfg.parentEle) : Polymer.dom(field).parentNode;
151+
exclude = cfg.exclude ? cfg.exclude : false;
145152
} else {
146-
this.config[key] = {};
147-
}
148-
149-
// If there was an initial value set in markup, use that
150-
// However, values set in the config will always 'win'
151-
if (field.value && value === null) {
152-
value = field.value;
153+
this.config[key] = {};
153154
}
154155

155156
// Store everything for reference later, assumes it's possible
156157
// to have a config which didn't include ALL of these items
157-
this.config[key].field = field;
158-
this.config[key].validation = validation;
159-
this.config[key].label = label;
160-
this.config[key].errorMsg = errorMsg;
161-
this.config[key].errorMsgEle = errorMsgEle;
162-
this.config[key].parentEle = parentEle;
163-
164-
// update data and DOM
165-
this._updateData(key, value);
166-
this._initialData[key] = value;
158+
this.config[key].field = field;
159+
this.config[key].validation = validation;
160+
this.config[key].validateIf = validateIf;
161+
this.config[key].label = label;
162+
this.config[key].errorMsg = errorMsg;
163+
this.config[key].errorMsgEle = errorMsgEle;
164+
this.config[key].parentEle = parentEle;
165+
this.config[key].exclude = exclude;
167166

168167
if (errorMsg && !errorMsgEle) {
169168
this._createErrorMsg(key, errorMsg, errorMsgEle, parentEle);
@@ -172,6 +171,28 @@
172171
}
173172

174173
if (label) this._createLabel(key, label, field, parentEle);
174+
}
175+
},
176+
177+
_initData: function() {
178+
for (var key in this.config) {
179+
var field = this._select('[name='+key+']'),
180+
exclude = this.config[key].exclude,
181+
value = this.data[key] || null;
182+
183+
if (!field) {
184+
throw 'There must be a corresponding DOM element for data[\''+key+'\']';
185+
}
186+
187+
// If there was an initial value set in markup, use that
188+
// However, values set in the config will always 'win'
189+
if (field.value && value === null) {
190+
value = field.value;
191+
}
192+
193+
// update data and DOM
194+
if (!exclude) this._updateData(key, value);
195+
this._initialData[key] = value;
175196

176197
// Populate the fields if necessary
177198
if (value && field.value !== value) {
@@ -181,7 +202,7 @@
181202
},
182203

183204
_createErrorMsg:function(key, errorMsg, errorMsgEle, parentEle) {
184-
var existingMsgEle = this._selectEle('._'+key+'-error-msg') || null;
205+
var existingMsgEle = this._select('._'+key+'-error-msg') || null;
185206

186207
if (!existingMsgEle) {
187208
// create one:
@@ -200,9 +221,9 @@
200221
},
201222

202223
_createLabel:function(key, label, field, parentEle) {
203-
var existingLblEle = this._selectEle('._'+key+'-label') || null,
204-
formLabel = null,
205-
labelTxt = null;
224+
var existingLblEle = this._select('._'+key+'-label') || null,
225+
formLabel = null,
226+
labelTxt = null;
206227

207228
if (!existingLblEle) {
208229
// create one:
@@ -228,18 +249,22 @@
228249

229250
// handle changes within the form
230251
_handleChanged: function(e) {
231-
var field = e.target,
232-
key = field.getAttribute('name'),
233-
value = null,
234-
validation = null,
235-
isFormElement = this.data.hasOwnProperty(key);
252+
var field = e.target,
253+
key = field.getAttribute('name'),
254+
value = null,
255+
validation = null,
256+
exclude = null,
257+
isFormElement = this.config.hasOwnProperty(key);
236258

237259
if (isFormElement) {
238-
value = e.detail.value;
239-
validation = this.config[key].validation;
260+
exclude = this.config[key].exclude ? this.config[key].exclude : false;
261+
value = e.detail.value;
262+
validation = this.config[key].validation;
240263

241-
this._updateData(key, value);
242-
this.unsaved = this._diffData();
264+
if (!exclude) {
265+
this._updateData(key, value);
266+
this.unsaved = this._diffData();
267+
}
243268

244269
if (validation) this._validateField(key, value);
245270

@@ -271,12 +296,13 @@
271296
this._invalidFields = [];
272297
this._validFields = [];
273298

274-
for (var key in this.data) {
299+
for (var key in this.config) {
275300
var value = this.data[key],
276301
validation = this.config[key].validation,
302+
validateIf = this.config[key].validateIf ? this.config[key].validateIf(key, value, this.data, this.view) : null,
277303
valid = false;
278304

279-
if (validation) {
305+
if (validation && (validateIf === null || validateIf === true)) {
280306
valid = this._validateField(key, value);
281307

282308
// Store valid and invalid for this validation pass
@@ -285,6 +311,9 @@
285311
} else {
286312
this._invalidFields.push(key);
287313
}
314+
} else if (validation && (validateIf !== null || validateIf === false)) {
315+
// clean up prior validations if they were there
316+
this.resetFieldValidation(key);
288317
}
289318

290319
// show messaging in the footer
@@ -319,9 +348,10 @@
319348
// },
320349

321350
_validateField: function(key, value) {
322-
var valid = false,
351+
var valid = null,
323352
field = this.config[key].field,
324353
validation = this.config[key].validation,
354+
errorMsg = this.config[key].errorMsg,
325355
errorMsgEle = this.config[key].errorMsgEle;
326356

327357
if (typeof(validation) === 'string') {
@@ -336,15 +366,23 @@
336366

337367
valid = result.length === testSet.length;
338368
} else if (typeof(validation) === 'function') {
339-
valid = validation(key, value, this.data);
369+
valid = validation(key, value, this.data, this.view);
340370
}
341371

342372
// show or hide messaging in the ui
373+
errorMsgEle.message = errorMsg;
343374
field.error = errorMsgEle.visible = !valid;
344-
375+
345376
return valid;
346377
},
347378

379+
resetFieldValidation: function(key) {
380+
var field = this.config[key].field,
381+
errorMsgEle = this.config[key].errorMsgEle;
382+
383+
field.error = errorMsgEle.visible = false;
384+
},
385+
348386
serializeForm: function() {
349387
this.validateFields();
350388

src/mm-test-form-view/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<script language="javascript" src="../../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
4+
<script language="javascript" src="../../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
55
<link rel="import" href="mm-test-form-view.html"/>
66
</head>
77
<body>

src/mm-test-form-view/mm-test-form-view.html

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
-->
77
<link rel="import" href="../../bower_components/polymer/polymer.html"/>
8+
<link rel="import" href="../shared/behaviors/refable.html"/>
89
<link rel="import" href="../mm-dropdown/mm-dropdown.html"/>
910
<link rel="import" href="../mm-list-item/mm-list-item.html"/>
1011
<link rel="import" href="../mm-group/mm-group.html"/>
@@ -15,7 +16,7 @@
1516
<dom-module id="mm-test-form-view">
1617
<link rel="import" type="css" href="mm-test-form-view.css"/>
1718
<template>
18-
<mm-form id="testForm" config="{{formConfig}}" data="{{formData}}">
19+
<mm-form id="testForm" config="{{formConfig}}" data="{{formData}}" view={{ref}}>
1920
<!-- row 1 -->
2021
<div class="col" span="1">
2122
<mm-input fitparent name="input" placeholder="Type a Number"></mm-input>
@@ -45,41 +46,56 @@
4546
</div>
4647

4748
<!-- row 2 -->
48-
<div class="col" span="2">
49+
<div id="customItemWrapper" class="col" span="2">
4950
<mm-header size="medium">Dimensions</mm-header>
51+
5052
<div id="customItem">
53+
5154
<mm-radio
5255
id="standardSize"
53-
group="sizes"
56+
group="sizes"
5457
checked
55-
on-selected="_handleRadioSelected"></mm-radio>
58+
on-selected="_sizeRadioSelected"></mm-radio>
59+
5660
<mm-dropdown
5761
id="standardSizeDdl"
58-
disabled$="{{!isStandard}}"
62+
disabled$="{{!standardSize}}"
63+
name="widthHeight"
5964
on-changed="_standardSizeChanged"
6065
placeholder="Select One">
6166
<mm-list-item>160x600</mm-list-item>
6267
<mm-list-item>728x90</mm-list-item>
6368
<mm-list-item>300x250</mm-list-item>
6469
</mm-dropdown>
70+
71+
<!-- validate-if$="{{standardSize}}" -->
72+
6573
<mm-radio
6674
id="nonStandardSize"
6775
group="sizes"
68-
on-selected="_handleRadioSelected"></mm-radio>
76+
on-selected="_sizeRadioSelected"></mm-radio>
77+
6978
<mm-group
7079
id="nonStandardSizeGroup"
71-
disabled$="{{isStandard}}"
80+
disabled$="{{standardSize}}"
7281
fitparent>
82+
7383
<mm-input
7484
name="width"
7585
placeholder="Width"
86+
validate-if="{{!standardSize}}"
7687
value="{{width}}"></mm-input>
88+
7789
<mm-input
7890
name="height"
7991
placeholder="Height"
92+
validate-if="{{!standardSize}}"
8093
value="{{height}}"></mm-input>
94+
8195
</mm-group>
96+
8297
</div>
98+
8399
<mm-form-message
84100
id="heightWidthError"
85101
type="error"

0 commit comments

Comments
 (0)