Skip to content

Commit 3df914a

Browse files
committed
Inline feedback icons on inputs and textarea
Configurable via form, error and validated as default. Also added "has-success" class when validated.
1 parent fe6f53b commit 3df914a

File tree

11 files changed

+77
-16
lines changed

11 files changed

+77
-16
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ General options most field types can handle:
179179
notitle: false, //Set to true to hide title
180180
description: "Street name", //A description, taken from schema if available
181181
validationMessage: "Oh noes, please write a proper address", //A custom validation error message
182-
onChange: "valueChanged(form.key,modelValue)" //onChange event handler, expression or function
182+
onChange: "valueChanged(form.key,modelValue)", //onChange event handler, expression or function
183+
feedback: false //inline feedback icons
183184
}
184185
```
185186

@@ -228,6 +229,34 @@ Ex.
228229
}
229230
```
230231

232+
### Inline feedback icons
233+
*input* and *textarea* based fields get inline status icons by default. A check
234+
when everything is valid and a cross when there are validation errors.
235+
236+
This can be turned off or configured to other icons. To turn off just
237+
set ```feedback``` to false. If set to a string that string is evaluated by
238+
a ```ngClass``` in the decorators scope. If not set att all the default value
239+
is ```{ 'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-remove': hasError() }```
240+
241+
ex. displaying an asterisk on required fields
242+
```javascript
243+
$sope.form = [
244+
{
245+
key: "name",
246+
feedback: "{ 'glyphicon': true, 'glyphicon-asterisk': form.requires && !hasSuccess && !hassError() ,'glyphicon-ok': hasSuccess(), 'glyphicon-remove': hasError() }"
247+
}
248+
```
249+
250+
Useful things in the decorators scope are
251+
252+
| Name | Description|
253+
|:---------------|:----------:|
254+
| hasSuccess() | *true* if field is valid and not pristine |
255+
| hasError() | *true* if field is invalid and not pristine |
256+
| ngModel | The controller of the ngModel directive, ex. ngModel.$valid |
257+
| form | The form definition for this field |
258+
259+
231260

232261
Specific options per type
233262
-------------------------

src/bootstrap-example.html

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,18 @@ <h3>Schema</h3>
137137
{
138138
key: "name",
139139
placeholder: "Check the console",
140-
onChange: "log(modelValue)"
140+
onChange: "log(modelValue)",
141+
feedback: "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }"
142+
},
143+
{
144+
key: "favorite",
145+
feedback: false
141146
},
142-
{ key: "favorite"},
143147
"attributes",
144-
"shoesize",
148+
{
149+
key: "shoesize",
150+
feedback: false
151+
},
145152
"things",
146153
"soul",
147154
{

src/directives/decorators/bootstrap/checkbox.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="checkbox" ng-class="{'has-error': hasError()}">
1+
<div class="checkbox" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}">
22
<label>
33
<input type="checkbox"
44
sf-changed="form"

src/directives/decorators/bootstrap/checkboxes.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}" ng-init="checkboxValues = {}">
1+
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}" ng-init="checkboxValues = {}">
22
<label ng-show="showTitle()">{{form.title}}</label>
33
<div class="checkbox" ng-repeat="(value,name) in form.titleMap" >
44
<label>
@@ -8,6 +8,7 @@
88
ng-change="$$value$$ = checkboxValuesToList(checkboxValues)" >
99
{{name}}
1010
</label>
11+
1112
</div>
1213
<span class="help-block" ng-show="form.description">{{form.description}}</span>
1314
</div>
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}">
2-
<label ng-show="showTitle()">{{form.title}}</label>
1+
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess(), 'has-feedback': form.feedback !== false }">
2+
<label class="control-label" ng-show="showTitle()">{{form.title}}</label>
33

44
<input ng-show="form.key"
55
type="{{form.type}}"
66
sf-changed="form"
77
placeholder="{{form.placeholder}}"
8-
class="form-control"
8+
class="form-control",
99
ng-required="form.required"
1010
ng-model="$$value$$"
1111
schema-validate="form.schema">
12-
12+
<span ng-if="form.feedback !== false"
13+
class="form-control-feedback"
14+
ng-class="evalInScope(form.feedback) || {'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-remove': hasError() }"></span>
1315
<span class="help-block">{{ (hasError() && errorMessage(schemaError())) || form.description}}</span>
1416
</div>

src/directives/decorators/bootstrap/radio-buttons.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}">
1+
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}">
22
<label ng-show="showTitle()">{{form.title}}</label>
33
<div class="btn-group">
44
<label class="btn btn-primary"

src/directives/decorators/bootstrap/radios.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}">
1+
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}">
22
<label ng-show="showTitle()">{{form.title}}</label>
33
<div class="radio" ng-repeat="(value,name) in form.titleMap" >
44
<label>

src/directives/decorators/bootstrap/select.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}">
1+
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess(), 'has-feedback': form.feedback !== false}">
22
<label ng-show="showTitle()">
33
{{form.title}}
44
</label>
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
<div class="form-group" ng-class="{'has-error': hasError()}">
1+
<div class="form-group has-feedback" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}">
22
<label ng-show="showTitle()">{{form.title}}</label>
33
<textarea class="form-control"
44
sf-changed="form"
55
ng-required="form.required"
66
ng-model="$$value$$"
77
schema-validate="form.schema"></textarea>
8-
8+
<span ng-if="form.feedback !== false"
9+
class="form-control-feedback"
10+
ng-class="evalInScope(form.feedback) || { 'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-remove': hasError() }"></span>
911
<span class="help-block">{{ (hasError() && errorMessage(schemaError())) || form.description}} </span>
1012
</div>

src/directives/schema-validate.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ angular.module('schemaForm').directive('schemaValidate',function(){
55
scope: false,
66
require: 'ngModel',
77
link: function(scope,element,attrs,ngModel) {
8+
//Since we have scope false this is the same scope
9+
//as the decorator
810
scope.ngModel = ngModel;
11+
912
var error = null;
1013
var schema = scope.$eval(attrs.schemaValidate);
1114

@@ -55,6 +58,10 @@ angular.module('schemaForm').directive('schemaValidate',function(){
5558
});
5659

5760
//This works since we now we're inside a decorator and that this is the decorators scope.
61+
scope.hasSuccess = function(){
62+
return scope.ngModel.$valid && !scope.ngModel.$pristine;
63+
};
64+
5865
scope.hasError = function(){
5966
return scope.ngModel.$invalid && !scope.ngModel.$pristine;
6067
};
@@ -65,4 +72,4 @@ angular.module('schemaForm').directive('schemaValidate',function(){
6572

6673
}
6774
};
68-
});
75+
});

src/services/decorators.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ angular.module('schemaForm').provider('schemaFormDecorators',['$compileProvider'
104104
return scope.$eval(expression,locals);
105105
};
106106

107+
/**
108+
* Evaluate an expression, i.e. scope.$eval
109+
* in this decorators scope
110+
* @param {string} expression
111+
* @param {Object} locals (optional)
112+
* @return {Any} the result of the expression
113+
*/
114+
scope.evalInScope = function(expression,locals) {
115+
if (expression) {
116+
return scope.$eval(expression,locals);
117+
}
118+
};
119+
107120
/**
108121
* Error message handler
109122
* An error can either be a schema validation message or a angular js validtion

0 commit comments

Comments
 (0)