Skip to content

Commit 5319458

Browse files
committed
Add support for nested attributes with DeepModel
1 parent b524b73 commit 5319458

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

README.md

+25
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,31 @@ Forms provide a `validate` method, which returns a dictionary of errors, or `nul
409409

410410
If you model provides a `validate` method, then this will be called when you call `Form.validate`. Forms are also validated when you call `commit`. See the Backbone documentation for more details on model validation.
411411

412+
Using nested attributes/fields
413+
==============================
414+
415+
If you are using a schema with nested attributes (using the `Object` type), you may want to include only some of the nested fields in a form. This can be accomplished by using 'path' syntax as in the example below.
416+
417+
However, due to Backbone's lack of support for nested model attributes, getting and setting values will not work out of the box. For this to work as expected you must adapt your model's get() and set() methods to handle the path names, or simply use [DeepModel](http://github.com/powmedia/backbone-deep-model) which will handle paths for you automatically.
418+
419+
var Model = Backbone.DeepModel.extend({
420+
schema: {
421+
title: {},
422+
author: { type: 'Object', subSchema: {
423+
id: { type: 'Number' },
424+
name: { type: 'Object', subSchema: {
425+
first: {},
426+
last: {}
427+
}}
428+
}}
429+
}
430+
});
431+
432+
var form = new Form({
433+
model: new Model,
434+
fields: ['title', 'author.id', 'author.name.last']
435+
}).render();
436+
412437

413438
Known issues
414439
============

src/backbone-forms.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
;(function() {
22

3+
//Support paths for nested attributes e.g. 'user.name'
4+
function getNested(obj, path) {
5+
var fields = path.split(".");
6+
var result = obj;
7+
for (var i = 0, n = fields.length; i < n; i++) {
8+
result = result[fields[i]];
9+
}
10+
return result;
11+
}
12+
13+
function getNestedSchema(obj, path) {
14+
path = path.replace(/\./g, '.subSchema.');
15+
return getNested(obj, path);
16+
}
17+
318
var helpers = {};
419
var validators = {};
520

@@ -193,10 +208,10 @@
193208
fields = this.fields,
194209
el = el || $(this.el),
195210
self = this;
196-
211+
197212
//Create form fields
198213
_.each(fieldsToRender, function(key) {
199-
var itemSchema = schema[key];
214+
var itemSchema = getNestedSchema(schema, key);
200215

201216
if (!itemSchema) throw "Field '"+key+"' not found in schema";
202217

test/form.js

+26
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,29 @@ test('Allows access to field views', function() {
204204
ok(form.fields.title instanceof Form.Field);
205205
ok(form.fields.author instanceof Form.Field);
206206
});
207+
208+
test("Supports picking nested fields from within Objects", function() {
209+
var Model = Backbone.Model.extend({
210+
schema: {
211+
title: {},
212+
author: { type: 'Object', subSchema: {
213+
id: { type: 'Number' },
214+
name: { type: 'Object', subSchema: {
215+
first: {},
216+
last: {}
217+
}}
218+
}}
219+
}
220+
});
221+
222+
var form = new Form({
223+
model: new Model,
224+
fields: ['title', 'author.id', 'author.name.last']
225+
}).render();
226+
227+
deepEqual(_.keys(form.fields), ['title', 'author.id', 'author.name.last']);
228+
229+
ok(form.fields['title'].editor instanceof Form.editors.Text);
230+
ok(form.fields['author.id'].editor instanceof Form.editors.Number);
231+
ok(form.fields['author.name.last'].editor instanceof Form.editors.Text);
232+
});

0 commit comments

Comments
 (0)