Skip to content

Commit aa8653d

Browse files
committed
Fix AutoForm.getFieldValue
So that it reacts properly when first called outside of the form, before the form has been rendered. Also attempt to limit unnecessary reruns.
1 parent 1f03a9f commit aa8653d

File tree

7 files changed

+173
-110
lines changed

7 files changed

+173
-110
lines changed

.jshintrc

Lines changed: 121 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,123 @@
1+
//.jshintrc
12
{
2-
"maxerr" : 50,
3-
"bitwise" : true,
4-
"camelcase" : true,
5-
"curly" : true,
6-
"eqeqeq" : true,
7-
"forin" : true,
8-
"immed" : false,
9-
"indent" : 2,
10-
"latedef" : false,
11-
"newcap" : false,
12-
"noarg" : true,
13-
"noempty" : true,
14-
"nonew" : false,
15-
"plusplus" : false,
16-
"quotmark" : false,
17-
"undef" : true,
18-
"unused" : true,
19-
"strict" : false,
20-
"trailing" : true,
21-
"maxparams" : false,
22-
"maxdepth" : false,
23-
"maxstatements" : false,
24-
"maxcomplexity" : false,
25-
"asi" : false,
26-
"boss" : false,
27-
"debug" : false,
28-
"eqnull" : false,
29-
"es5" : false,
30-
"esnext" : false,
31-
"moz" : false,
32-
"evil" : false,
33-
"expr" : false,
34-
"funcscope" : false,
35-
"globalstrict" : false,
36-
"iterator" : false,
37-
"lastsemic" : false,
38-
"laxbreak" : false,
39-
"laxcomma" : false,
40-
"loopfunc" : false,
41-
"multistr" : false,
42-
"proto" : false,
43-
"scripturl" : false,
44-
"smarttabs" : false,
45-
"shadow" : false,
46-
"sub" : false,
47-
"supernew" : false,
48-
"validthis" : false,
49-
"browser" : true,
50-
"couch" : false,
51-
"devel" : true,
52-
"dojo" : false,
53-
"jquery" : false,
54-
"mootools" : false,
55-
"node" : false,
56-
"nonstandard" : false,
57-
"prototypejs" : false,
58-
"rhino" : false,
59-
"worker" : false,
60-
"wsh" : false,
61-
"yui" : false,
62-
"nomen" : false,
63-
"onevar" : false,
64-
"passfail" : false,
65-
"white" : false,
66-
"predef" : [
67-
"Meteor",
68-
"Accounts",
69-
"Session",
70-
"Template",
71-
"check",
72-
"Match",
73-
"Tracker",
74-
"Deps",
75-
"EJSON",
76-
"Email",
77-
"Package",
78-
"Tinytest",
79-
"Mongo",
80-
"Npm",
81-
"Assets",
82-
"Packages",
83-
"process",
84-
"LocalCollection",
85-
"_",
86-
"Random",
87-
"HTTP",
88-
"$",
89-
"UI",
90-
"Blaze"
91-
]
3+
// JSHint Meteor Configuration File
4+
// Match the Meteor Style Guide
5+
//
6+
// By @raix with contributions from @aldeed and @awatson1978
7+
// Source https://github.com/raix/Meteor-jshintrc
8+
//
9+
// See http://jshint.com/docs/ for more details
10+
11+
"maxerr" : 50, // {int} Maximum error before stopping
12+
13+
// Enforcing
14+
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
15+
"camelcase" : false, // false: Identifiers do not need to be in camelCase. We would like to enforce this except for when interacting with our api objects which use snakeCase properties.
16+
"curly" : false, // false: Do not require {} for every new block or scope
17+
"eqeqeq" : true, // true: Require triple equals (===) for comparison
18+
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
19+
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
20+
"indent" : 2, // {int} Number of spaces to use for indentation
21+
"latedef" : false, // true: Require variables/functions to be defined before being used
22+
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
23+
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
24+
"noempty" : true, // true: Prohibit use of empty blocks
25+
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
26+
"plusplus" : false, // true: Prohibit use of `++` & `--`
27+
"quotmark" : false, // Quotation mark consistency:
28+
// false : do nothing (default)
29+
// true : ensure whatever is used is consistent
30+
// "single" : require single quotes
31+
// "double" : require double quotes
32+
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
33+
"unused" : true, // true: Require all defined variables be used
34+
"strict" : false, // false: Do not require all functions to be run in ES5 Strict Mode
35+
"trailing" : true, // true: Prohibit trailing whitespaces
36+
"maxparams" : false, // {int} Max number of formal params allowed per function
37+
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
38+
"maxstatements" : false, // {int} Max number statements per function
39+
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
40+
"maxlen" : 250, // {int} Max number of characters per line
41+
42+
// Relaxing
43+
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
44+
"boss" : false, // true: Tolerate assignments where comparisons would be expected
45+
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
46+
"eqnull" : false, // true: Tolerate use of `== null`
47+
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
48+
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
49+
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
50+
// (ex: `for each`, multiple try/catch, function expression…)
51+
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
52+
"expr" : true, // true: Tolerate `ExpressionStatement` as Programs
53+
"funcscope" : false, // true: Tolerate defining variables inside control statements"
54+
"globalstrict" : true, // true: Allow global "use strict" (also enables 'strict')
55+
"iterator" : false, // true: Tolerate using the `__iterator__` property
56+
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
57+
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
58+
"laxcomma" : false, // true: Tolerate comma-first style coding
59+
"loopfunc" : false, // true: Tolerate functions being defined in loops
60+
"multistr" : false, // true: Tolerate multi-line strings
61+
"proto" : false, // true: Tolerate using the `__proto__` property
62+
"scripturl" : false, // true: Tolerate script-targeted URLs
63+
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
64+
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
65+
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
66+
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
67+
"validthis" : false, // true: Tolerate using this in a non-constructor function
68+
69+
// Environments
70+
"browser" : true, // Web Browser (window, document, etc)
71+
"couch" : false, // CouchDB
72+
"devel" : true, // Development/debugging (alert, confirm, etc)
73+
"dojo" : false, // Dojo Toolkit
74+
"jquery" : false, // jQuery
75+
"mootools" : false, // MooTools
76+
"node" : false, // Node.js
77+
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
78+
"prototypejs" : false, // Prototype and Scriptaculous
79+
"rhino" : false, // Rhino
80+
"worker" : false, // Web Workers
81+
"wsh" : false, // Windows Scripting Host
82+
"yui" : false, // Yahoo User Interface
83+
//"meteor" : false, // Meteor.js
84+
85+
// Legacy
86+
"nomen" : false, // true: Prohibit dangling `_` in variables
87+
"onevar" : false, // true: Allow only one `var` statement per function
88+
"passfail" : false, // true: Stop on first error
89+
"white" : false, // true: Check against strict whitespace and indentation rules
90+
91+
// Custom globals, from http://docs.meteor.com, in the order they appear there
92+
"globals" : {
93+
"Meteor": false,
94+
"DDP": false,
95+
"Mongo": false, //Meteor.Collection renamed to Mongo.Collection
96+
"Session": false,
97+
"Accounts": false,
98+
"Template": false,
99+
"Blaze": false,
100+
"Spacebars": false,
101+
"Match": false,
102+
"check": false,
103+
"Tracker": false,
104+
"ReactiveVar": false,
105+
"ReactiveDict": false,
106+
"EJSON": false,
107+
"HTTP": false,
108+
"Email": false,
109+
"Assets": false,
110+
"Package": false,
111+
"App": false, //mobile-config.js
112+
"cordova": false,
113+
"Cordova": false,
114+
115+
// globals useful when creating Meteor packages
116+
"Npm": false,
117+
"Tinytest": false,
118+
119+
// common Meteor packages
120+
"_": false, // Underscore.js
121+
"$": false
122+
}
92123
}

.versions

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
22
33
44
@@ -16,7 +16,7 @@ [email protected]
1616
1717
1818
19-
local-test:aldeed:[email protected].0
19+
local-test:aldeed:[email protected].1
2020
2121
2222

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ forms with automatic insert and update events, and automatic reactive validation
66

77
## Change Log
88

9+
### 5.4.1
10+
11+
* Fix `AutoForm.getFieldValue` so that it reacts properly when first called outside of the form, before the form has been rendered. Also attempt to limit unnecessary reruns.
12+
913
### 5.4.0
1014

1115
* New `autoform.group` option. See "Grouping Fields" in README. (Thanks @SachaG)

autoform-api.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,11 @@ AutoForm.getFieldValue = function autoFormGetFieldValue(fieldName, formId) {
404404
var template = Tracker.nonreactive(function () {
405405
return AutoForm.templateInstanceForForm(formId);
406406
});
407-
if (!template ||
408-
!template.fieldValuesReady.get() ||
409-
!template.view ||
410-
!template.view._domrange ||
411-
template.view.isDestroyed) {
407+
408+
if (!template) {
409+
if (formId) {
410+
AutoForm.rerunWhenFormRenderedOrDestroyed(formId);
411+
}
412412
return;
413413
}
414414

@@ -419,6 +419,12 @@ AutoForm.getFieldValue = function autoFormGetFieldValue(fieldName, formId) {
419419
}
420420
template.formValues[fieldName].depend();
421421

422+
if (!template.view ||
423+
!template.view._domrange ||
424+
template.view.isDestroyed) {
425+
return;
426+
}
427+
422428
var doc = AutoForm.getFormValues(formId, template, null, false);
423429
if (!doc) {
424430
return;
@@ -1250,3 +1256,18 @@ setDefaults = function setDefaults(data) {
12501256

12511257
return data;
12521258
};
1259+
1260+
var waitingForForms = {};
1261+
AutoForm.rerunWhenFormRenderedOrDestroyed = function (formId) {
1262+
if (!_.has(waitingForForms, formId)) {
1263+
waitingForForms[formId] = new Tracker.Dependency();
1264+
}
1265+
waitingForForms[formId].depend();
1266+
};
1267+
1268+
AutoForm.triggerFormRenderedDestroyedReruns = function (formId) {
1269+
if (!_.has(waitingForForms, formId)) {
1270+
waitingForForms[formId] = new Tracker.Dependency();
1271+
}
1272+
waitingForForms[formId].changed();
1273+
};

components/afFieldInput/afFieldInput.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,12 @@ Template.afFieldInput.helpers({
6969
// blocks involved.
7070
// See https://github.com/aldeed/meteor-autoform/issues/461
7171
var template = AutoForm.templateInstanceForForm();
72-
updateTrackedFieldValue(template, c.atts.name);
73-
72+
if (template.view.isRendered) {
73+
// No need to do this on first run because we'll rerun the value functions
74+
// once the form is rendered anyway
75+
updateTrackedFieldValue(template, c.atts.name);
76+
}
77+
7478
// Build input data context
7579
var iData = getInputData(defs, c.atts, value, ss.label(c.atts.name), form.type);
7680

components/autoForm/autoForm.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global AutoForm, ReactiveVar, arrayTracker, Hooks, MongoObject, updateAllTrackedFieldValues, Utility, setDefaults */
1+
/* global AutoForm, ReactiveVar, arrayTracker, Hooks, MongoObject, Utility, setDefaults */
22

33
Template.autoForm.helpers({
44
atts: function autoFormTplAtts() {
@@ -68,8 +68,6 @@ Template.autoForm.created = function autoFormCreated() {
6868
// be wiped out by further client validation.
6969
template._stickyErrors = {};
7070

71-
template.fieldValuesReady = new ReactiveVar(false);
72-
7371
template.autorun(function (c) {
7472
var data = Template.currentData(); // rerun when current data changes
7573
var formId = data.id;
@@ -127,17 +125,19 @@ Template.autoForm.created = function autoFormCreated() {
127125
} else {
128126
AutoForm.reactiveFormData.sourceDoc(formId, null);
129127
}
130-
131-
// This ensures that anything dependent on field values will properly
132-
// react to field values set from the database document. That is,
133-
// computations dependent on AutoForm.getFieldValue will rerun properly
134-
// when the form is initially rendered using values from `doc`.
135-
updateAllTrackedFieldValues(template);
136128
});
137129
};
138130

139131
Template.autoForm.rendered = function autoFormRendered() {
140-
this.fieldValuesReady.set(true);
132+
var lastId;
133+
this.autorun(function () {
134+
var data = Template.currentData(); // rerun when current data changes
135+
136+
if (data.id === lastId) return;
137+
lastId = data.id;
138+
139+
AutoForm.triggerFormRenderedDestroyedReruns(data.id);
140+
});
141141
};
142142

143143
Template.autoForm.destroyed = function autoFormDestroyed() {
@@ -152,4 +152,7 @@ Template.autoForm.destroyed = function autoFormDestroyed() {
152152

153153
// Unregister form preservation
154154
AutoForm.formPreserve.unregisterForm(formId);
155+
156+
// Trigger value reruns
157+
AutoForm.triggerFormRenderedDestroyedReruns(formId);
155158
};

package.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Package.describe({
22
name: "aldeed:autoform",
33
summary: "Easily create forms with automatic insert and update, and automatic reactive validation.",
44
git: "https://github.com/aldeed/meteor-autoform.git",
5-
version: "5.4.0"
5+
version: "5.4.1"
66
});
77

88
Package.onUse(function(api) {

0 commit comments

Comments
 (0)