Added validation to form: required, minlength, maxlength
diff --git a/views/ngXosLib/xosHelpers/spec/ui/form.test.js b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
index 32e91be..567f145 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/form.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
@@ -102,6 +102,7 @@
describe('the _getFieldFormat method', () => {
it('should return string', () => {
expect(service._getFieldFormat('string')).toEqual('string');
+ expect(service._getFieldFormat(null)).toEqual('string');
});
it('should return mail', () => {
expect(service._getFieldFormat('test@onlab.us')).toEqual('email');
@@ -166,6 +167,7 @@
scope.config = {
exclude: ['excludedField'],
+ formName: 'testForm',
actions: [
{
label: 'Save',
@@ -261,6 +263,42 @@
expect(isolatedScope.ngModel.enabled).toEqual(true);
});
});
+
+ describe('the custom validation options', () => {
+ beforeEach(() => {
+ scope.config.fields.first_name.validators = {
+ minlength: 10,
+ maxlength: 15,
+ required: true
+ };
+
+ scope.$digest();
+ });
+
+ it('should validate required', () => {
+ scope.model.first_name = null;
+ scope.$digest();
+
+ expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
+ expect(isolatedScope.testForm.first_name.$error.required).toBeTruthy();
+ });
+
+ it('should validate minlength', () => {
+ scope.model.first_name = 'short';
+ scope.$digest();
+
+ expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
+ expect(isolatedScope.testForm.first_name.$error.minlength).toBeTruthy();
+ });
+
+ it('should validate maxlength', () => {
+ scope.model.first_name = 'this is way too long!';
+ scope.$digest();
+
+ expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
+ expect(isolatedScope.testForm.first_name.$error.maxlength).toBeTruthy();
+ });
+ });
});
});
});
diff --git a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
index eb92a05..782f03f 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
@@ -32,6 +32,10 @@
let availableErrors = [
{
+ type: 'required',
+ message: 'Field required'
+ },
+ {
type: 'email',
message: 'This is not a valid email'
},
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form.component.js
index 3a80fc1..715ead3 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form.component.js
@@ -85,7 +85,15 @@
<ng-form name="vm.{{vm.config.formName || 'form'}}">
<div class="form-group" ng-repeat="(name, field) in vm.formField">
<label>{{field.label}}</label>
- <input ng-if="field.type !== 'boolean'" type="{{field.type}}" name="{{name}}" class="form-control" ng-model="vm.ngModel[name]"/>
+ <input
+ ng-if="field.type !== 'boolean'"
+ type="{{field.type}}"
+ name="{{name}}"
+ class="form-control"
+ ng-model="vm.ngModel[name]"
+ ng-minlength="field.validators.minlength || 0"
+ ng-maxlength="field.validators.maxlength || 2000"
+ ng-required="field.validators.required || false"/>
<span class="boolean-field" ng-if="field.type === 'boolean'">
<button
class="btn btn-success"
@@ -100,6 +108,7 @@
<i class="glyphicon glyphicon-remove"></i>
</button>
</span>
+ <!-- <pre>{{vm[vm.config.formName][name].$error | json}}</pre> -->
<xos-validation errors="vm[vm.config.formName || 'form'][name].$error"></xos-validation>
</div>
<div class="form-group" ng-if="vm.config.actions">
@@ -138,7 +147,7 @@
return;
}
this.formField = XosFormHelpers.buildFormStructure(XosFormHelpers.parseModelField(_.difference(Object.keys(model), this.excludedField)), this.config.fields, model);
- });
+ }, true);
}
}
@@ -164,7 +173,7 @@
}
// check if a string is a number
- if(!isNaN(value)){
+ if(!isNaN(value) && value !== null){
return 'number';
}
@@ -173,6 +182,11 @@
return 'email';
}
+ // if null return string
+ if(value === null){
+ return 'string';
+ }
+
return typeof value;
};
@@ -181,10 +195,11 @@
customField = customField || {};
return _.reduce(Object.keys(modelField), (form, f) => {
+
form[f] = {
label: (customField[f] && customField[f].label) ? `${customField[f].label}:` : LabelFormatter.format(f),
type: (customField[f] && customField[f].type) ? customField[f].type : this._getFieldFormat(model[f]),
- validators: {}
+ validators: (customField[f] && customField[f].validators) ? customField[f].validators : {}
};
if(form[f].type === 'date'){
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation.component.js
index c5ea993..5cb7d08 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation.component.js
@@ -56,6 +56,9 @@
template: `
<div>
<!-- <pre>{{vm.errors.email | json}}</pre> -->
+ <xos-alert config="vm.config" show="vm.errors.required !== undefined && vm.errors.required !== false">
+ Field required
+ </xos-alert>
<xos-alert config="vm.config" show="vm.errors.email !== undefined && vm.errors.email !== false">
This is not a valid email
</xos-alert>
diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 63eab05..60dd85d 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -78,7 +78,7 @@
scope: {
errors: '='
},
- template: '\n <div>\n <!-- <pre>{{vm.errors.email | json}}</pre> -->\n <xos-alert config="vm.config" show="vm.errors.email !== undefined && vm.errors.email !== false">\n This is not a valid email\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.minlength !== undefined && vm.errors.minlength !== false">\n Too short\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.maxlength !== undefined && vm.errors.maxlength !== false">\n Too long\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.custom !== undefined && vm.errors.custom !== false">\n Field invalid\n </xos-alert>\n </div>\n ',
+ template: '\n <div>\n <!-- <pre>{{vm.errors.email | json}}</pre> -->\n <xos-alert config="vm.config" show="vm.errors.required !== undefined && vm.errors.required !== false">\n Field required\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.email !== undefined && vm.errors.email !== false">\n This is not a valid email\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.minlength !== undefined && vm.errors.minlength !== false">\n Too short\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.maxlength !== undefined && vm.errors.maxlength !== false">\n Too long\n </xos-alert>\n <xos-alert config="vm.config" show="vm.errors.custom !== undefined && vm.errors.custom !== false">\n Field invalid\n </xos-alert>\n </div>\n ',
transclude: true,
bindToController: true,
controllerAs: 'vm',
@@ -497,7 +497,7 @@
config: '=',
ngModel: '='
},
- template: '\n <ng-form name="vm.{{vm.config.formName || \'form\'}}">\n <div class="form-group" ng-repeat="(name, field) in vm.formField">\n <label>{{field.label}}</label>\n <input ng-if="field.type !== \'boolean\'" type="{{field.type}}" name="{{name}}" class="form-control" ng-model="vm.ngModel[name]"/>\n <span class="boolean-field" ng-if="field.type === \'boolean\'">\n <button\n class="btn btn-success"\n ng-show="vm.ngModel[name]"\n ng-click="vm.ngModel[name] = false">\n <i class="glyphicon glyphicon-ok"></i>\n </button>\n <button\n class="btn btn-danger"\n ng-show="!vm.ngModel[name]"\n ng-click="vm.ngModel[name] = true">\n <i class="glyphicon glyphicon-remove"></i>\n </button>\n </span>\n <xos-validation errors="vm[vm.config.formName || \'form\'][name].$error"></xos-validation>\n </div>\n <div class="form-group" ng-if="vm.config.actions">\n <button role="button" href=""\n ng-repeat="action in vm.config.actions"\n ng-click="action.cb(vm.ngModel)"\n class="btn btn-{{action.class}}"\n title="{{action.label}}">\n <i class="glyphicon glyphicon-{{action.icon}}"></i>\n {{action.label}}\n </button>\n </div>\n </ng-form>\n ',
+ template: '\n <ng-form name="vm.{{vm.config.formName || \'form\'}}">\n <div class="form-group" ng-repeat="(name, field) in vm.formField">\n <label>{{field.label}}</label>\n <input\n ng-if="field.type !== \'boolean\'"\n type="{{field.type}}"\n name="{{name}}"\n class="form-control"\n ng-model="vm.ngModel[name]"\n ng-minlength="field.validators.minlength || 0"\n ng-maxlength="field.validators.maxlength || 2000"\n ng-required="field.validators.required || false"/>\n <span class="boolean-field" ng-if="field.type === \'boolean\'">\n <button\n class="btn btn-success"\n ng-show="vm.ngModel[name]"\n ng-click="vm.ngModel[name] = false">\n <i class="glyphicon glyphicon-ok"></i>\n </button>\n <button\n class="btn btn-danger"\n ng-show="!vm.ngModel[name]"\n ng-click="vm.ngModel[name] = true">\n <i class="glyphicon glyphicon-remove"></i>\n </button>\n </span>\n <!-- <pre>{{vm[vm.config.formName][name].$error | json}}</pre> -->\n <xos-validation errors="vm[vm.config.formName || \'form\'][name].$error"></xos-validation>\n </div>\n <div class="form-group" ng-if="vm.config.actions">\n <button role="button" href=""\n ng-repeat="action in vm.config.actions"\n ng-click="action.cb(vm.ngModel)"\n class="btn btn-{{action.class}}"\n title="{{action.label}}">\n <i class="glyphicon glyphicon-{{action.icon}}"></i>\n {{action.label}}\n </button>\n </div>\n </ng-form>\n ',
bindToController: true,
controllerAs: 'vm',
controller: ["$scope", "$log", "_", "XosFormHelpers", function controller($scope, $log, _, XosFormHelpers) {
@@ -524,7 +524,7 @@
return;
}
_this.formField = XosFormHelpers.buildFormStructure(XosFormHelpers.parseModelField(_.difference(Object.keys(model), _this.excludedField)), _this.config.fields, model);
- });
+ }, true);
}]
};
}).service('XosFormHelpers', ["_", "LabelFormatter", function (_, LabelFormatter) {
@@ -549,7 +549,7 @@
}
// check if a string is a number
- if (!isNaN(value)) {
+ if (!isNaN(value) && value !== null) {
return 'number';
}
@@ -558,6 +558,11 @@
return 'email';
}
+ // if null return string
+ if (value === null) {
+ return 'string';
+ }
+
return typeof value === 'undefined' ? 'undefined' : _typeof(value);
};
@@ -566,10 +571,11 @@
customField = customField || {};
return _.reduce(Object.keys(modelField), function (form, f) {
+
form[f] = {
label: customField[f] && customField[f].label ? customField[f].label + ':' : LabelFormatter.format(f),
type: customField[f] && customField[f].type ? customField[f].type : _this2._getFieldFormat(model[f]),
- validators: {}
+ validators: customField[f] && customField[f].validators ? customField[f].validators : {}
};
if (form[f].type === 'date') {