Skip to content

Commit 9940002

Browse files
committed
adding error handling
1 parent dcb3789 commit 9940002

File tree

4 files changed

+69
-16
lines changed

4 files changed

+69
-16
lines changed

src/fields/baseField.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export default
99
created: function(){
1010
let state = {
1111
'$dirty': false,
12-
'$active': false
12+
'$active': false,
13+
'$hasError': false
1314
};
1415
this.$set(this.form, this.field.key, state);
1516
},
@@ -39,5 +40,19 @@ export default
3940
onKeydown: function(e){
4041
this.runFunction('onKeydown', e);
4142
}
43+
},
44+
computed: {
45+
hasError: function(){
46+
if ( this.form[ this.field.key ].$dirty == false || this.form[ this.field.key ].$active == true ) {
47+
return false;
48+
}
49+
let errors = this.form.$errors[ this.field.key ];
50+
let hasErrors = false;
51+
Object.keys( errors ).forEach( err => {
52+
if ( errors[err] ) hasErrors = true;
53+
});
54+
this.$set(this.form[ this.field.key ], '$hasError', hasErrors);
55+
return hasErrors;
56+
}
4257
}
4358
};

src/fields/fieldInput.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="form-group formly-input" :class="[ to.type, {'formly-has-value': model[field.key], 'formly-has-focus': form[field.key].$active}]">
2+
<div class="form-group formly-input" :class="[ to.inputType, {'formly-has-value': model[field.key], 'formly-has-focus': form[field.key].$active}, 'has-error': form[field.key].$hasError]">
33
<label v-if="to.label" :for="to.id ? to.id : null">{{to.label}}</label>
44
<input class="form-control" :class="to.classes" :id="to.id ? to.id : null" type="text" v-model="model[field.key]" @blur="onBlur" @focus="onFocus" @click="onClick" @change="onChange" @keyup="onKeyup" @keydown="onKeydown" v-formly-atts="to.atts" v-formly-input-type="to.inputType">
55
</div>

src/fields/fieldList.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<div class="checkbox formly-list" :id="to.id" :class="to.classes">
33

44
<label v-for="option in field.options">
5-
<input v-if="!to.type || to.type == 'checkbox'" type="checkbox" v-model="model[field.key]" :value="option.value || option" @blur="onBlur" @focus="onFocus" @click="onClick" @change="onChange" @keyup="onKeyup" @keydown="onKeydown" v-formly-atts="to.atts">
6-
<input v-if="to.type == 'radio'" type="radio" v-model="model[field.key]" :value="option.value || option" @blur="onBlur" @focus="onFocus" @click="onClick" @change="onChange" @keyup="onKeyup" @keydown="onKeydown" v-formly-atts="to.atts">
5+
<input v-if="!to.inputType || to.inputType == 'checkbox'" type="checkbox" v-model="model[field.key]" :value="option.value || option" @blur="onBlur" @focus="onFocus" @click="onClick" @change="onChange" @keyup="onKeyup" @keydown="onKeydown" v-formly-atts="to.atts">
6+
<input v-if="to.inputType == 'radio'" type="radio" v-model="model[field.key]" :value="option.value || option" @blur="onBlur" @focus="onFocus" @click="onClick" @change="onChange" @keyup="onKeyup" @keydown="onKeydown" v-formly-atts="to.atts">
77
{{option.label || option}}
88
</label>
99

@@ -16,7 +16,7 @@
1616
mixins: [baseField],
1717
created: function(){
1818
//set the default value to be an array if it's a checkbox
19-
let type = this.to.type;
19+
let type = this.to.inputType;
2020
if ( (!type || type == 'checkbox') && this.model[ this.field.key ] == '') this.$set(this.model, this.field.key, []);
2121
}
2222
}

test/unit/specs/index.spec.js

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function trigger (target, event, process) {
3333
function describeFunctions(formlyElement, inputElement, inputType = 'text', options){
3434
beforeEach(() => {
3535
data.fields[0].type = formlyElement;
36-
data.fields[0].templateOptions.type = inputType;
36+
data.fields[0].templateOptions.inputType = inputType;
3737
if ( typeof options != 'undefined' ) data.fields[0].options = options;
3838
spy = sinon.spy();
3939
});
@@ -103,7 +103,7 @@ function describeFunctions(formlyElement, inputElement, inputType = 'text', opti
103103
function describeAttributes(inputElement, testPlaceholder = true){
104104
beforeEach(()=>{
105105
data.fields[0].type = inputElement;
106-
data.fields[0].templateOptions.type = 'text';
106+
data.fields[0].templateOptions.inputType = 'text';
107107
});
108108

109109
it('attributes', () => {
@@ -142,7 +142,7 @@ function describeAttributes(inputElement, testPlaceholder = true){
142142
function describeConditional(inputElement){
143143
it('label', (done) => {
144144
data.fields[0].type = inputElement;
145-
data.fields[0].templateOptions.type = 'text';
145+
data.fields[0].templateOptions.inputType = 'text';
146146
data.fields[0].templateOptions.label = '';
147147
createForm(data);
148148

@@ -177,6 +177,22 @@ describe('Bootstrap Field Inputs', () => {
177177
};
178178
});
179179

180+
describe('Errors', () => {
181+
it('should receive an error state', () => {
182+
data.fields[0].type = 'input';
183+
data.fields[0].required = true;
184+
createForm();
185+
186+
expect(data.form['test'].$hasError).to.be.false;
187+
trigger(vm.$el.querySelectorAll('input')[0], 'focus');
188+
expect(data.form['test'].$hasError).to.be.false;
189+
expect(data.form['test'].$active).to.be.true;
190+
191+
trigger(vm.$el.querySelectorAll('input')[0], 'change');
192+
expect(data.form['test'].$hasError).to.be.false;
193+
});
194+
});
195+
180196
describe('Input', () => {
181197

182198
describe('functions',() =>{
@@ -187,7 +203,7 @@ describe('Bootstrap Field Inputs', () => {
187203
describeAttributes('input');
188204
it('should have input type as a class', () => {
189205
data.fields[0].type = 'input';
190-
data.fields[0].templateOptions.type = 'text';
206+
data.fields[0].templateOptions.inputType = 'text';
191207
createForm(data);
192208

193209
let els = vm.$el.querySelectorAll('.text');
@@ -203,7 +219,7 @@ describe('Bootstrap Field Inputs', () => {
203219

204220
it('layout', (done) => {
205221
data.fields[0].type = 'input';
206-
data.fields[0].templateOptions.type = 'text';
222+
data.fields[0].templateOptions.inputType = 'text';
207223
createForm(data);
208224

209225
let inputs = vm.$el.querySelectorAll('input');
@@ -226,7 +242,7 @@ describe('Bootstrap Field Inputs', () => {
226242

227243
it('adds active and focus classes', (done) => {
228244
data.fields[0].type = 'input';
229-
data.fields[0].templateOptions.type = 'text';
245+
data.fields[0].templateOptions.inputType = 'text';
230246
createForm(data);
231247

232248
expect(vm.$el.querySelectorAll('.formly-has-focus')).to.be.length(0);
@@ -243,7 +259,7 @@ describe('Bootstrap Field Inputs', () => {
243259

244260
it('defaults to text', () => {
245261
data.fields[0].type = 'input';
246-
data.fields[0].templateOptions.type = undefined;
262+
data.fields[0].templateOptions.inputType = undefined;
247263
createForm(data);
248264

249265
let inputs = vm.$el.querySelectorAll('input');
@@ -363,7 +379,7 @@ describe('Bootstrap Field Inputs', () => {
363379

364380
it('array options', () => {
365381
data.fields[0].type = 'list';
366-
data.fields[0].templateOptions.type = 'checkbox';
382+
data.fields[0].templateOptions.inputType = 'checkbox';
367383
data.fields[0].options = ['one', 'two', 'three'];
368384
createForm();
369385

@@ -378,7 +394,7 @@ describe('Bootstrap Field Inputs', () => {
378394

379395
it('object options', () => {
380396
data.fields[0].type = 'list';
381-
data.fields[0].templateOptions.type = 'checkbox'
397+
data.fields[0].templateOptions.inputType = 'checkbox'
382398
data.fields[0].options = [
383399
{ label: 'Foo', value: 'bar' },
384400
{ label: 'Bar', value: 'foo' }
@@ -418,7 +434,7 @@ describe('Bootstrap Field Inputs', () => {
418434

419435
it('multiple values', (done) => {
420436
data.fields[0].type = 'list';
421-
data.fields[0].templateOptions.type = 'checkbox';
437+
data.fields[0].templateOptions.inputType = 'checkbox';
422438
data.fields[0].options = ['one', 'two'];
423439
createForm();
424440

@@ -433,7 +449,7 @@ describe('Bootstrap Field Inputs', () => {
433449

434450
it('single value', (done) => {
435451
data.fields[0].type = 'list';
436-
data.fields[0].templateOptions.type = 'radio';
452+
data.fields[0].templateOptions.inputType = 'radio';
437453
data.fields[0].options = ['one', 'two'];
438454
createForm();
439455

@@ -445,6 +461,28 @@ describe('Bootstrap Field Inputs', () => {
445461
done();
446462
}, 0);
447463
});
464+
465+
it('only shows a checkbox', () => {
466+
data.fields[0].type = 'list';
467+
data.fields[0].options = ['one', 'two'];
468+
createForm();
469+
let inputs = vm.$el.querySelectorAll('input');
470+
expect(inputs).to.be.length(2);
471+
expect(inputs[0].type).to.equal('checkbox');
472+
expect(inputs[1].type).to.equal('checkbox');
473+
});
474+
475+
it('only shows a radio box', () => {
476+
data.fields[0].type = 'list';
477+
data.fields[0].templateOptions.inputType = 'radio';
478+
data.fields[0].options = ['one', 'two'];
479+
createForm();
480+
let inputs = vm.$el.querySelectorAll('input');
481+
expect(inputs).to.be.length(2);
482+
expect(inputs[0].type).to.equal('radio');
483+
expect(inputs[1].type).to.equal('radio');
484+
});
485+
448486
});
449487

450488
});

0 commit comments

Comments
 (0)