Skip to content

Commit 9a8da19

Browse files
committed
Better propagation of form
So we don't need to eval or wait for the form def.
1 parent ebe0de8 commit 9a8da19

File tree

4 files changed

+196
-226
lines changed

4 files changed

+196
-226
lines changed

src/directives/field.js

+82-94
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ angular.module('schemaForm').directive('sfField',
1111
scope: true,
1212
require: '?^sfSchema',
1313
link: {
14-
pre: function(scope) {
14+
pre: function(scope, element, attrs) {
1515
//The ngModelController is used in some templates and
1616
//is needed for error messages,
1717
scope.$on('schemaFormPropagateNgModelController', function(event, ngModel) {
@@ -20,11 +20,10 @@ angular.module('schemaForm').directive('sfField',
2020
scope.ngModel = ngModel;
2121
});
2222

23-
//make sure to overwrite form here so that we don't inherit it by accident
24-
scope.form = null;
23+
// Fetch our form.
24+
scope.form = element.data('sfForm');
2525
},
2626
post: function(scope, element, attrs, sfSchema) {
27-
2827
//Keep error prone logic from the template
2928
scope.showTitle = function() {
3029
return scope.form && scope.form.notitle !== true && scope.form.title;
@@ -140,100 +139,89 @@ angular.module('schemaForm').directive('sfField',
140139
);
141140
};
142141

143-
// Rebind our part of the form to the scope.
144-
var once = scope.$watch(attrs.sfField, function(form) {
145-
if (form) {
146-
// Workaround for 'updateOn' error from ngModelOptions
147-
// see https://github.com/Textalk/angular-schema-form/issues/255
148-
// and https://github.com/Textalk/angular-schema-form/issues/206
149-
form.ngModelOptions = form.ngModelOptions || {};
150-
scope.form = form;
151-
152-
153-
// Where there is a key there is probably a ngModel
154-
if (form.key) {
155-
// It looks better with dot notation.
156-
scope.$on(
157-
'schemaForm.error.' + form.key.join('.'),
158-
function(event, error, validationMessage, validity) {
159-
if (validationMessage === true || validationMessage === false) {
160-
validity = validationMessage;
161-
validationMessage = undefined;
162-
}
142+
var form = scope.form;
143+
144+
// Where there is a key there is probably a ngModel
145+
if (form.key) {
146+
// It looks better with dot notation.
147+
scope.$on(
148+
'schemaForm.error.' + form.key.join('.'),
149+
function(event, error, validationMessage, validity) {
150+
if (validationMessage === true || validationMessage === false) {
151+
validity = validationMessage;
152+
validationMessage = undefined;
153+
}
154+
155+
if (scope.ngModel && error) {
156+
if (scope.ngModel.$setDirty) {
157+
scope.ngModel.$setDirty();
158+
} else {
159+
// FIXME: Check that this actually works on 1.2
160+
scope.ngModel.$dirty = true;
161+
scope.ngModel.$pristine = false;
162+
}
163163

164-
if (scope.ngModel && error) {
165-
if (scope.ngModel.$setDirty) {
166-
scope.ngModel.$setDirty();
167-
} else {
168-
// FIXME: Check that this actually works on 1.2
169-
scope.ngModel.$dirty = true;
170-
scope.ngModel.$pristine = false;
171-
}
172-
173-
// Set the new validation message if one is supplied
174-
// Does not work when validationMessage is just a string.
175-
if (validationMessage) {
176-
if (!form.validationMessage) {
177-
form.validationMessage = {};
178-
}
179-
form.validationMessage[error] = validationMessage;
180-
}
181-
182-
scope.ngModel.$setValidity(error, validity === true);
183-
184-
if (validity === true) {
185-
// Setting or removing a validity can change the field to believe its valid
186-
// but its not. So lets trigger its validation as well.
187-
scope.$broadcast('schemaFormValidate');
188-
}
189-
}
190-
});
191-
192-
// Clean up the model when the corresponding form field is $destroy-ed.
193-
// Default behavior can be supplied as a globalOption, and behavior can be overridden in the form definition.
194-
scope.$on('$destroy', function() {
195-
// If the entire schema form is destroyed we don't touch the model
196-
if (!scope.externalDestructionInProgress) {
197-
var destroyStrategy = form.destroyStrategy ||
198-
(scope.options && scope.options.destroyStrategy) || 'remove';
199-
// No key no model, and we might have strategy 'retain'
200-
if (form.key && destroyStrategy !== 'retain') {
201-
202-
// Get the object that has the property we wan't to clear.
203-
var obj = scope.model;
204-
if (form.key.length > 1) {
205-
obj = sfSelect(form.key.slice(0, form.key.length - 1), obj);
206-
}
207-
208-
// We can get undefined here if the form hasn't been filled out entirely
209-
if (obj === undefined) {
210-
return;
211-
}
212-
213-
// Type can also be a list in JSON Schema
214-
var type = (form.schema && form.schema.type) || '';
215-
216-
// Empty means '',{} and [] for appropriate types and undefined for the rest
217-
//console.log('destroy', destroyStrategy, form.key, type, obj);
218-
if (destroyStrategy === 'empty' && type.indexOf('string') !== -1) {
219-
obj[form.key.slice(-1)] = '';
220-
} else if (destroyStrategy === 'empty' && type.indexOf('object') !== -1) {
221-
obj[form.key.slice(-1)] = {};
222-
} else if (destroyStrategy === 'empty' && type.indexOf('array') !== -1) {
223-
obj[form.key.slice(-1)] = [];
224-
} else if (destroyStrategy === 'null') {
225-
obj[form.key.slice(-1)] = null;
226-
} else {
227-
delete obj[form.key.slice(-1)];
228-
}
164+
// Set the new validation message if one is supplied
165+
// Does not work when validationMessage is just a string.
166+
if (validationMessage) {
167+
if (!form.validationMessage) {
168+
form.validationMessage = {};
229169
}
170+
form.validationMessage[error] = validationMessage;
230171
}
231-
});
232-
}
233172

234-
once();
235-
}
236-
});
173+
scope.ngModel.$setValidity(error, validity === true);
174+
175+
if (validity === true) {
176+
// Setting or removing a validity can change the field to believe its valid
177+
// but its not. So lets trigger its validation as well.
178+
scope.$broadcast('schemaFormValidate');
179+
}
180+
}
181+
});
182+
183+
// Clean up the model when the corresponding form field is $destroy-ed.
184+
// Default behavior can be supplied as a globalOption, and behavior can be overridden
185+
// in the form definition.
186+
scope.$on('$destroy', function() {
187+
// If the entire schema form is destroyed we don't touch the model
188+
if (!scope.externalDestructionInProgress) {
189+
var destroyStrategy = form.destroyStrategy ||
190+
(scope.options && scope.options.destroyStrategy) || 'remove';
191+
// No key no model, and we might have strategy 'retain'
192+
if (form.key && destroyStrategy !== 'retain') {
193+
194+
// Get the object that has the property we wan't to clear.
195+
var obj = scope.model;
196+
if (form.key.length > 1) {
197+
obj = sfSelect(form.key.slice(0, form.key.length - 1), obj);
198+
}
199+
200+
// We can get undefined here if the form hasn't been filled out entirely
201+
if (obj === undefined) {
202+
return;
203+
}
204+
205+
// Type can also be a list in JSON Schema
206+
var type = (form.schema && form.schema.type) || '';
207+
208+
// Empty means '',{} and [] for appropriate types and undefined for the rest
209+
//console.log('destroy', destroyStrategy, form.key, type, obj);
210+
if (destroyStrategy === 'empty' && type.indexOf('string') !== -1) {
211+
obj[form.key.slice(-1)] = '';
212+
} else if (destroyStrategy === 'empty' && type.indexOf('object') !== -1) {
213+
obj[form.key.slice(-1)] = {};
214+
} else if (destroyStrategy === 'empty' && type.indexOf('array') !== -1) {
215+
obj[form.key.slice(-1)] = [];
216+
} else if (destroyStrategy === 'null') {
217+
obj[form.key.slice(-1)] = null;
218+
} else {
219+
delete obj[form.key.slice(-1)];
220+
}
221+
}
222+
}
223+
});
224+
}
237225
}
238226
}
239227
};

src/directives/message.js

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
angular.module('schemaForm').directive('sfMessage',
22
['$injector', 'sfErrorMessage', function($injector, sfErrorMessage) {
3+
4+
//Inject sanitizer if it exists
5+
var $sanitize = $injector.has('$sanitize') ?
6+
$injector.get('$sanitize') : function(html) { return html; };
7+
38
return {
49
scope: false,
510
restrict: 'EA',
611
link: function(scope, element, attrs) {
712

8-
//Inject sanitizer if it exists
9-
var $sanitize = $injector.has('$sanitize') ?
10-
$injector.get('$sanitize') : function(html) { return html; };
11-
1213
var message = '';
13-
1414
if (attrs.sfMessage) {
1515
scope.$watch(attrs.sfMessage, function(msg) {
1616
if (msg) {
@@ -28,8 +28,6 @@ angular.module('schemaForm').directive('sfMessage',
2828
if (valid && !scope.hasError()) {
2929
element.html(message);
3030
} else {
31-
32-
3331
var errors = [];
3432
angular.forEach(((scope.ngModel && scope.ngModel.$error) || {}), function(status, code) {
3533
if (status) {
@@ -62,14 +60,8 @@ angular.module('schemaForm').directive('sfMessage',
6260
}
6361
};
6462

65-
// When link occurs we might not have form with the new builder.
66-
var once = scope.$watch('form', function(form) {
67-
if (form) {
68-
update();
69-
once();
70-
}
71-
});
72-
63+
// Update once.
64+
update();
7365

7466
scope.$watchCollection('ngModel.$error', function() {
7567
if (scope.ngModel) {

0 commit comments

Comments
 (0)