Skip to content

Commit 4ceb03d

Browse files
committed
Merge branch 'hotfix/0.8.8'
2 parents 90b920b + dab0024 commit 4ceb03d

File tree

8 files changed

+175
-57
lines changed

8 files changed

+175
-57
lines changed

CHANGELOG

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
v0.8.8
2+
------
3+
* Don't rely on documentFragment.children @davidlgj
4+
* Restored "template" type support with the builder. @davidlgj
5+
* Fixed defaults in array items. @davidlgj
6+
17
v0.8.7
28
------
3-
* Moved common builder functions from angular-schema-form-bootstrap decorator.
4-
* Bugfx for the new builder.
9+
* Moved common builder functions from angular-schema-form-bootstrap decorator. @davidlgj
10+
* Bugfx for the new builder. @davidlgj
511

612
v0.8.6
713
------
8-
* Removed left over console.timeEnd
14+
* Removed left over console.timeEnd @davidlgj
915

1016
v0.8.5
1117
------

dist/schema-form.js

+82-26
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
255255
'"modelValue": model' + (strKey[0] === '[' ? '' : '.') + strKey + '})';
256256
}
257257

258-
var children = args.fieldFrag.children;
258+
var children = args.fieldFrag.children || args.fieldFrag.childNodes;
259259
for (var i = 0; i < children.length; i++) {
260260
var child = children[i];
261261
var ngIf = child.getAttribute('ng-if');
@@ -351,7 +351,7 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
351351
// measure optmization. A good start is probably a cache of DOM nodes for a particular
352352
// template that can be cloned instead of using innerHTML
353353
var div = document.createElement('div');
354-
var template = templateFn(field.template) || templateFn([decorator['default'].template]);
354+
var template = templateFn(f, field) || templateFn(f, decorator['default']);
355355
div.innerHTML = template;
356356

357357
// Move node to a document fragment, we don't want the div.
@@ -375,11 +375,14 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
375375

376376
};
377377

378+
// Let the form definiton override builders if it wants to.
379+
var builderFn = f.builder || field.builder;
380+
378381
// Builders are either a function or a list of functions.
379-
if (typeof field.builder === 'function') {
380-
field.builder(args);
382+
if (typeof builderFn === 'function') {
383+
builderFn(args);
381384
} else {
382-
field.builder.forEach(function(fn) { fn(args); });
385+
builderFn.forEach(function(fn) { fn(args); });
383386
}
384387

385388
// Append
@@ -396,8 +399,11 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
396399
* Builds a form from a canonical form definition
397400
*/
398401
build: function(form, decorator, slots, lookup) {
399-
return build(form, decorator, function(url) {
400-
return $templateCache.get(url);
402+
return build(form, decorator, function(form, field) {
403+
if (form.type === 'template') {
404+
return form.template;
405+
}
406+
return $templateCache.get(field.template);
401407
}, slots, undefined, undefined, lookup);
402408

403409
},
@@ -1324,7 +1330,7 @@ angular.module('schemaForm').provider('schemaForm',
13241330

13251331
var service = {};
13261332

1327-
service.merge = function(schema, form, ignore, options, readonly) {
1333+
service.merge = function(schema, form, ignore, options, readonly, asyncTemplates) {
13281334
form = form || ['*'];
13291335
options = options || {};
13301336

@@ -1395,13 +1401,13 @@ angular.module('schemaForm').provider('schemaForm',
13951401

13961402
//if it's a type with items, merge 'em!
13971403
if (obj.items) {
1398-
obj.items = service.merge(schema, obj.items, ignore, options, obj.readonly);
1404+
obj.items = service.merge(schema, obj.items, ignore, options, obj.readonly, asyncTemplates);
13991405
}
14001406

14011407
//if its has tabs, merge them also!
14021408
if (obj.tabs) {
14031409
angular.forEach(obj.tabs, function(tab) {
1404-
tab.items = service.merge(schema, tab.items, ignore, options, obj.readonly);
1410+
tab.items = service.merge(schema, tab.items, ignore, options, obj.readonly, asyncTemplates);
14051411
});
14061412
}
14071413

@@ -1410,6 +1416,13 @@ angular.module('schemaForm').provider('schemaForm',
14101416
if (obj.type === 'checkbox' && angular.isUndefined(obj.schema['default'])) {
14111417
obj.schema['default'] = false;
14121418
}
1419+
1420+
// Special case: template type with tempplateUrl that's needs to be loaded before rendering
1421+
// TODO: this is not a clean solution. Maybe something cleaner can be made when $ref support
1422+
// is introduced since we need to go async then anyway
1423+
if (asyncTemplates && obj.type === 'template' && !obj.template && obj.templateUrl) {
1424+
asyncTemplates.push(obj);
1425+
}
14131426

14141427
return obj;
14151428
}));
@@ -2281,28 +2294,52 @@ function(sel, sfPath, schemaForm) {
22812294
});
22822295

22832296
scope.appendToArray = function() {
2284-
22852297
var empty;
22862298

2287-
// Same old add empty things to the array hack :(
2288-
if (scope.form && scope.form.schema) {
2289-
if (scope.form.schema.items) {
2290-
if (scope.form.schema.items.type === 'object') {
2291-
empty = {};
2292-
} else if (scope.form.schema.items.type === 'array') {
2293-
empty = [];
2294-
}
2295-
}
2296-
}
2297-
2299+
// Create and set an array if needed.
22982300
var model = scope.modelArray;
22992301
if (!model) {
2300-
// Create and set an array if needed.
23012302
var selection = sfPath.parse(attrs.sfNewArray);
23022303
model = [];
23032304
sel(selection, scope, model);
23042305
scope.modelArray = model;
23052306
}
2307+
2308+
// Same old add empty things to the array hack :(
2309+
if (scope.form && scope.form.schema && scope.form.schema.items) {
2310+
2311+
var items = scope.form.schema.items;
2312+
if (items.type && items.type.indexOf('object') !== -1) {
2313+
empty = {};
2314+
2315+
// Check for possible defaults
2316+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
2317+
empty = angular.isDefined(items['default']) ? items['default'] : empty;
2318+
2319+
// Check for defaults further down in the schema.
2320+
// If the default instance sets the new array item to something falsy, i.e. null
2321+
// then there is no need to go further down.
2322+
if (empty) {
2323+
schemaForm.traverseSchema(items, function(prop, path) {
2324+
if (angular.isDefined(prop['default'])) {
2325+
sel(path, empty, prop['default']);
2326+
}
2327+
});
2328+
}
2329+
}
2330+
2331+
} else if (items.type && items.type.indexOf('array') !== -1) {
2332+
empty = [];
2333+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
2334+
empty = items['default'] || empty;
2335+
}
2336+
} else {
2337+
// No type? could still have defaults.
2338+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
2339+
empty = items['default'] || empty;
2340+
}
2341+
}
2342+
}
23062343
model.push(empty);
23072344

23082345
return model;
@@ -2369,8 +2406,8 @@ FIXME: real documentation
23692406

23702407
angular.module('schemaForm')
23712408
.directive('sfSchema',
2372-
['$compile', 'schemaForm', 'schemaFormDecorators', 'sfSelect', 'sfPath', 'sfBuilder',
2373-
function($compile, schemaForm, schemaFormDecorators, sfSelect, sfPath, sfBuilder) {
2409+
['$compile', '$http', '$templateCache', '$q','schemaForm', 'schemaFormDecorators', 'sfSelect', 'sfPath', 'sfBuilder',
2410+
function($compile, $http, $templateCache, $q, schemaForm, schemaFormDecorators, sfSelect, sfPath, sfBuilder) {
23742411

23752412
return {
23762413
scope: {
@@ -2429,8 +2466,27 @@ angular.module('schemaForm')
24292466

24302467
// Common renderer function, can either be triggered by a watch or by an event.
24312468
var render = function(schema, form) {
2432-
var merged = schemaForm.merge(schema, form, ignore, scope.options);
2469+
var asyncTemplates = [];
2470+
var merged = schemaForm.merge(schema, form, ignore, scope.options, undefined, asyncTemplates);
2471+
2472+
if (asyncTemplates.length > 0) {
2473+
// Pre load all async templates and put them on the form for the builder to use.
2474+
$q.all(asyncTemplates.map(function(form) {
2475+
return $http.get(form.templateUrl, {cache: $templateCache}).then(function(res) {
2476+
form.template = res.data;
2477+
});
2478+
})).then(function() {
2479+
internalRender(schema, form, merged);
2480+
});
2481+
2482+
} else {
2483+
internalRender(schema, form, merged);
2484+
}
2485+
2486+
2487+
};
24332488

2489+
var internalRender = function(schema, form, merged) {
24342490
// Create a new form and destroy the old one.
24352491
// Not doing keeps old form elements hanging around after
24362492
// they have been removed from the DOM

dist/schema-form.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-schema-form",
3-
"version": "0.8.7",
3+
"version": "0.8.8",
44
"description": "Create complex forms from a JSON schema with angular.",
55
"repository": "Textalk/angular-schema-form",
66
"main": "dist/schema-form.min.js",

src/directives/newArray.js

+37-13
Original file line numberDiff line numberDiff line change
@@ -129,28 +129,52 @@ function(sel, sfPath, schemaForm) {
129129
});
130130

131131
scope.appendToArray = function() {
132-
133132
var empty;
134133

135-
// Same old add empty things to the array hack :(
136-
if (scope.form && scope.form.schema) {
137-
if (scope.form.schema.items) {
138-
if (scope.form.schema.items.type === 'object') {
139-
empty = {};
140-
} else if (scope.form.schema.items.type === 'array') {
141-
empty = [];
142-
}
143-
}
144-
}
145-
134+
// Create and set an array if needed.
146135
var model = scope.modelArray;
147136
if (!model) {
148-
// Create and set an array if needed.
149137
var selection = sfPath.parse(attrs.sfNewArray);
150138
model = [];
151139
sel(selection, scope, model);
152140
scope.modelArray = model;
153141
}
142+
143+
// Same old add empty things to the array hack :(
144+
if (scope.form && scope.form.schema && scope.form.schema.items) {
145+
146+
var items = scope.form.schema.items;
147+
if (items.type && items.type.indexOf('object') !== -1) {
148+
empty = {};
149+
150+
// Check for possible defaults
151+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
152+
empty = angular.isDefined(items['default']) ? items['default'] : empty;
153+
154+
// Check for defaults further down in the schema.
155+
// If the default instance sets the new array item to something falsy, i.e. null
156+
// then there is no need to go further down.
157+
if (empty) {
158+
schemaForm.traverseSchema(items, function(prop, path) {
159+
if (angular.isDefined(prop['default'])) {
160+
sel(path, empty, prop['default']);
161+
}
162+
});
163+
}
164+
}
165+
166+
} else if (items.type && items.type.indexOf('array') !== -1) {
167+
empty = [];
168+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
169+
empty = items['default'] || empty;
170+
}
171+
} else {
172+
// No type? could still have defaults.
173+
if (!scope.options || scope.options.setSchemaDefaults !== false) {
174+
empty = items['default'] || empty;
175+
}
176+
}
177+
}
154178
model.push(empty);
155179

156180
return model;

src/directives/schema-form.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ FIXME: real documentation
55

66
angular.module('schemaForm')
77
.directive('sfSchema',
8-
['$compile', 'schemaForm', 'schemaFormDecorators', 'sfSelect', 'sfPath', 'sfBuilder',
9-
function($compile, schemaForm, schemaFormDecorators, sfSelect, sfPath, sfBuilder) {
8+
['$compile', '$http', '$templateCache', '$q','schemaForm', 'schemaFormDecorators', 'sfSelect', 'sfPath', 'sfBuilder',
9+
function($compile, $http, $templateCache, $q, schemaForm, schemaFormDecorators, sfSelect, sfPath, sfBuilder) {
1010

1111
return {
1212
scope: {
@@ -65,8 +65,27 @@ angular.module('schemaForm')
6565

6666
// Common renderer function, can either be triggered by a watch or by an event.
6767
var render = function(schema, form) {
68-
var merged = schemaForm.merge(schema, form, ignore, scope.options);
68+
var asyncTemplates = [];
69+
var merged = schemaForm.merge(schema, form, ignore, scope.options, undefined, asyncTemplates);
70+
71+
if (asyncTemplates.length > 0) {
72+
// Pre load all async templates and put them on the form for the builder to use.
73+
$q.all(asyncTemplates.map(function(form) {
74+
return $http.get(form.templateUrl, {cache: $templateCache}).then(function(res) {
75+
form.template = res.data;
76+
});
77+
})).then(function() {
78+
internalRender(schema, form, merged);
79+
});
80+
81+
} else {
82+
internalRender(schema, form, merged);
83+
}
84+
85+
86+
};
6987

88+
var internalRender = function(schema, form, merged) {
7089
// Create a new form and destroy the old one.
7190
// Not doing keeps old form elements hanging around after
7291
// they have been removed from the DOM

src/services/builder.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
113113
'"modelValue": model' + (strKey[0] === '[' ? '' : '.') + strKey + '})';
114114
}
115115

116-
var children = args.fieldFrag.children;
116+
var children = args.fieldFrag.children || args.fieldFrag.childNodes;
117117
for (var i = 0; i < children.length; i++) {
118118
var child = children[i];
119119
var ngIf = child.getAttribute('ng-if');
@@ -209,7 +209,7 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
209209
// measure optmization. A good start is probably a cache of DOM nodes for a particular
210210
// template that can be cloned instead of using innerHTML
211211
var div = document.createElement('div');
212-
var template = templateFn(field.template) || templateFn([decorator['default'].template]);
212+
var template = templateFn(f, field) || templateFn(f, decorator['default']);
213213
div.innerHTML = template;
214214

215215
// Move node to a document fragment, we don't want the div.
@@ -233,11 +233,14 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
233233

234234
};
235235

236+
// Let the form definiton override builders if it wants to.
237+
var builderFn = f.builder || field.builder;
238+
236239
// Builders are either a function or a list of functions.
237-
if (typeof field.builder === 'function') {
238-
field.builder(args);
240+
if (typeof builderFn === 'function') {
241+
builderFn(args);
239242
} else {
240-
field.builder.forEach(function(fn) { fn(args); });
243+
builderFn.forEach(function(fn) { fn(args); });
241244
}
242245

243246
// Append
@@ -254,8 +257,11 @@ angular.module('schemaForm').provider('sfBuilder', ['sfPathProvider', function(s
254257
* Builds a form from a canonical form definition
255258
*/
256259
build: function(form, decorator, slots, lookup) {
257-
return build(form, decorator, function(url) {
258-
return $templateCache.get(url);
260+
return build(form, decorator, function(form, field) {
261+
if (form.type === 'template') {
262+
return form.template;
263+
}
264+
return $templateCache.get(field.template);
259265
}, slots, undefined, undefined, lookup);
260266

261267
},

0 commit comments

Comments
 (0)