Skip to content

Commit 413f9f6

Browse files
committed
Added ngModelOptions and global options
Global defaults can be set with "sf-options", among them 'formDefaults' useful for setting things like ngModelOptions and validationMessage for an entire form.
1 parent ec21b47 commit 413f9f6

File tree

12 files changed

+285
-86
lines changed

12 files changed

+285
-86
lines changed

docs/index.md

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Documentation
22
=============
33

44
1. [Basic Usage](#basic-usage)
5+
1. [Global Options](#global-options)
56
1. [Form types](#form-types)
67
1. [Default form types](#default-form-types)
78
1. [Form definitions](#form-definitions)
@@ -10,6 +11,7 @@ Documentation
1011
1. [onChange](#onchange)
1112
1. [Validation Messages](#validation-messages)
1213
1. [Inline feedback icons](#inline-feedback-icons)
14+
1. [ngModelOptions](#ngmodeloptions)
1315
1. [Specific options and types](#specific-options-and-types)
1416
1. [fieldset and section](#fieldset-and-section)
1517
1. [conditional](#conditional)
@@ -77,6 +79,35 @@ Example with custom submit buttons:
7779
</div>
7880
```
7981

82+
Global Options
83+
--------------
84+
Schema Form also have two options you can set globally via the `sf-options`
85+
attribute which should be placed along side `sf-schema`.
86+
87+
`sf-options` takes an object with the following possible attributes.
88+
89+
90+
| Attribute | |
91+
|:--------------|:------------------------|
92+
| supressPropertyTitles | by default schema form uses the property name in the schema as a title if none is specified, set this to true to disable that behavior |
93+
| formDefaults | an object that will be used as a default for all form definitions |
94+
95+
*formDefaults* is mostly useful for setting global [ngModelOptions](#ngmodeloptions)
96+
i.e. changing the entire form to validate on blur. But can also be used to set
97+
[Validation Messages](#validation-messages) for all fields if you like a bit more
98+
friendlier messages.
99+
100+
Ex.
101+
```html
102+
<div ng-controller="FormController">
103+
<form sf-schema="schema"
104+
sf-form="form"
105+
sf-model="model"
106+
sf-options="{ formDefaults: { ngModelOptions: { updateOn: 'blur' } }}"></form>
107+
</div>
108+
```
109+
110+
80111

81112
Form types
82113
----------
@@ -205,14 +236,15 @@ Standard Options
205236
General options most field types can handle:
206237
```javascript
207238
{
208-
key: "address.street", //The dot notatin to the attribute on the model
209-
type: "text", //Type of field
210-
title: "Street", //Title of field, taken from schema if available
211-
notitle: false, //Set to true to hide title
212-
description: "Street name", //A description, taken from schema if available, can be HTML
213-
validationMessage: "Oh noes, please write a proper address", //A custom validation error message
214-
onChange: "valueChanged(form.key,modelValue)", //onChange event handler, expression or function
215-
feedback: false //inline feedback icons
239+
key: "address.street", // The dot notatin to the attribute on the model
240+
type: "text", // Type of field
241+
title: "Street", // Title of field, taken from schema if available
242+
notitle: false, // Set to true to hide title
243+
description: "Street name", // A description, taken from schema if available, can be HTML
244+
validationMessage: "Oh noes, please write a proper address", // A custom validation error message
245+
onChange: "valueChanged(form.key,modelValue)", // onChange event handler, expression or function
246+
feedback: false, // Inline feedback icons
247+
ngModelOptions: { ... } // Passed along to ng-model-options
216248
}
217249
```
218250

@@ -241,26 +273,29 @@ $scope.form = [
241273

242274
### Validation Messages
243275

244-
Per default all error messages but "Required" comes from the schema validator
276+
Per default all error messages comes from the schema validator
245277
[tv4](https://github.com/geraintluff/tv4), this might or might not work for you.
246-
If you supply a ```validationMessage``` property in the form definition, and if its value is a
278+
If you supply a `validationMessage` property in the form definition, and if its value is a
247279
string that will be used instead on any validation error.
248280

249281
If you need more fine grained control you can supply an object instead with keys matching the error
250-
codes of [tv4](https://github.com/geraintluff/tv4). See ```tv4.errorCodes```
282+
codes of [tv4](https://github.com/geraintluff/tv4). See `tv4.errorCodes`
251283

252284
Ex.
253285
```javascript
254286
{
255287
key: "address.street",
256288
validationMessage: {
257289
tv4.errorCodes.STRING_LENGTH_SHORT: "Address is too short, man.",
258-
"default": "Just write a proper address, will you?", //Special catch all error message
259-
"required": "I needz an address plz" //Used for required if specified
290+
"default": "Just write a proper address, will you?" //Special catch all error message
260291
}
261292
}
262293
```
263294

295+
You can also set a global `validationMessage` in *formDefaults* see
296+
[Global Options](#global-options).
297+
298+
264299
### Inline feedback icons
265300
*input* and *textarea* based fields get inline status icons by default. A check
266301
when everything is valid and a cross when there are validation errors.
@@ -289,6 +324,26 @@ Useful things in the decorators scope are
289324
| form | The form definition for this field |
290325

291326

327+
### ngModelOptions
328+
Angular 1.3 introduces a new directive, *ngModelOptions*, which let's you set
329+
a couple of options that change how the directive *ng-model* works. Schema Form
330+
uses *ng-model* to bind against fields and therefore changing theses options
331+
might be usefule for you.
332+
333+
One thing you can do is to change the update behavior of *ng-model*, this is how
334+
you get form fields that validate on blur instead of directly on change.
335+
336+
Ex.
337+
```javascript
338+
{
339+
key: "email",
340+
ngModelOptions: { updateOn: 'blur' }
341+
}
342+
```
343+
344+
See [Global Options](#global-options) for an example how you set entire form
345+
to validate on blur.
346+
292347

293348
Specific options and types
294349
--------------------------

examples/bootstrap-example.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ <h1>Schema Form Example</h1>
3535
<div class="row">
3636
<div class="col-sm-4">
3737
<h3>The Generated Form</h3>
38-
<form name="ngform" sf-model="modelData" sf-form="form" sf-schema="schema" sf-decorator-name="{{decorator}}"></form>
38+
<form name="ngform" sf-model="modelData" sf-form="form" sf-schema="schema"></form>
3939
<h3>Model</h3>
4040
<pre ng-cloak>{{pretty()}}</pre>
4141
</div>

src/directives/decorators/bootstrap/array.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div sf-array="form" ng-model="$$value$$">
1+
<div sf-array="form" ng-model="$$value$$" ng-model-options="form.ngModelOptions">
22
<h3 ng-show="form.title && form.notitle !== true">{{ form.title }}</h3>
33
<ul class="list-group" ng-model="modelArray" ui-sortable>
44
<li class="list-group-item" ng-repeat="item in modelArray track by $index">

src/directives/decorators/bootstrap/checkbox.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<input type="checkbox"
44
sf-changed="form"
55
ng-model="$$value$$"
6+
ng-model-options="form.ngModelOptions"
67
schema-validate="form">
78
<span ng-bind-html="form.title"></span>
89
</label>

src/directives/decorators/bootstrap/default.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
sf-changed="form"
77
placeholder="{{form.placeholder}}"
88
class="form-control"
9+
ng-model-options="form.ngModelOptions"
910
ng-model="$$value$$"
1011
schema-validate="form">
1112
<span ng-if="form.feedback !== false"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
sf-changed="form"
1111
style="display: none;"
1212
ng-model="$$value$$"
13+
ng-model-options="form.ngModelOptions"
1314
ng-value="item.value">
1415
<span ng-bind-html="item.name"></span>
1516
</label>

src/directives/decorators/bootstrap/radios.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<input type="radio"
66
sf-changed="form"
77
ng-model="$$value$$"
8+
ng-model-options="form.ngModelOptions"
89
ng-value="item.value">
910
<span ng-bind-html="item.name"></span>
1011
</label>

src/directives/decorators/bootstrap/select.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
{{form.title}}
44
</label>
55
<select ng-model="$$value$$"
6+
ng-model-options="form.ngModelOptions"
67
sf-changed="form"
78
class="form-control"
89
schema-validate="form"

src/directives/decorators/bootstrap/textarea.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<textarea class="form-control"
44
sf-changed="form"
55
ng-model="$$value$$"
6+
ng-model-options="form.ngModelOptions"
67
schema-validate="form"></textarea>
78
<!-- disabled until we unbreak the css
89
<span ng-if="form.feedback !== false"

src/directives/schema-form.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ function($compile, schemaForm, schemaFormDecorators, sfSelect){
7171
lastDigest.schema = schema;
7272
lastDigest.form = form;
7373

74-
//FIXME: traverse schema and model and set default values.
74+
// Check for options
75+
var options = scope.$eval(attrs.sfOptions);
7576

76-
var merged = schemaForm.merge(schema,form,ignore);
77+
var merged = schemaForm.merge(schema,form,ignore,options);
7778
var frag = document.createDocumentFragment();
7879

7980
//make the form available to decorators

src/services/schema-form.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,20 @@ angular.module('schemaForm').provider('schemaForm',['sfPathProvider', function(s
4343

4444
//Creates a form object with all common properties
4545
var stdFormObj = function(name,schema,options) {
46-
var f = {};
47-
f.title = schema.title || name[0];
46+
options = options || {};
47+
var f = options.global && options.global.formDefaults ? angular.copy(options.global.formDefaults) : {};
48+
49+
if (options.global && options.global.supressPropertyTitles === true) {
50+
f.title = schema.title;
51+
} else {
52+
f.title = schema.title || name[0];
53+
}
54+
4855
if (schema.description) f.description = schema.description;
4956
if (options.required === true || schema.required === true) f.required = true;
5057
if (schema.maxLength) f.maxlength = schema.maxLength;
5158
if (schema.minLength) f.minlength = schema.maxLength;
52-
if (schema.readOnly || schema.readonly) f.readonly = schema.readOnly || schema.readonly;
59+
if (schema.readOnly || schema.readonly) f.readonly = true;
5360
if (schema.minimum) f.minimum = schema.minimum + (schema.exclusiveMinimum?1:0);
5461
if (schema.maximum) f.maximum = schema.maximum - (schema.exclusiveMaximum?1:0);
5562

@@ -58,8 +65,9 @@ angular.module('schemaForm').provider('schemaForm',['sfPathProvider', function(s
5865
if (schema.enumNames) f.titleMap = canonicalTitleMap(schema.enumNames);
5966
f.schema = schema;
6067

61-
// Ng model options doesn't play nice with undefined
62-
f.ngModelOptions = {};
68+
// Ng model options doesn't play nice with undefined, might be defined
69+
// globally though
70+
f.ngModelOptions = f.ngModelOptions || {};
6371
return f;
6472
};
6573

@@ -268,10 +276,12 @@ angular.module('schemaForm').provider('schemaForm',['sfPathProvider', function(s
268276

269277
var service = {};
270278

271-
service.merge = function(schema,form,ignore) {
279+
service.merge = function(schema, form, ignore, options) {
272280
form = form || ["*"];
281+
options = options || {};
282+
283+
var stdForm = service.defaults(schema, ignore, options);
273284

274-
var stdForm = service.defaults(schema,ignore);
275285
//simple case, we have a "*", just put the stdForm there
276286
var idx = form.indexOf("*");
277287
if (idx !== -1) {
@@ -337,10 +347,11 @@ angular.module('schemaForm').provider('schemaForm',['sfPathProvider', function(s
337347
/**
338348
* Create form defaults from schema
339349
*/
340-
service.defaults = function(schema,ignore) {
350+
service.defaults = function(schema, ignore, globalOptions) {
341351
var form = [];
342352
var lookup = {}; //Map path => form obj for fast lookup in merging
343353
ignore = ignore || {};
354+
globalOptions = globalOptions || {};
344355

345356
if (schema.type === "object") {
346357
angular.forEach(schema.properties,function(v,k){
@@ -351,7 +362,8 @@ angular.module('schemaForm').provider('schemaForm',['sfPathProvider', function(s
351362
path: k, //path to this property in dot notation. Root object has no name
352363
lookup: lookup, //extra map to register with. Optimization for merger.
353364
ignore: ignore, //The ignore list of paths (sans root level name)
354-
required: required //Is it required? (v4 json schema style)
365+
required: required, //Is it required? (v4 json schema style)
366+
global: globalOptions // Global options, including form defaults
355367
});
356368
if (def) {
357369
form.push(def);

0 commit comments

Comments
 (0)