Skip to content

Commit a7b5ba6

Browse files
committed
Fix timing and add more items to onChange and condition scopes
1 parent 039b27f commit a7b5ba6

File tree

7 files changed

+160
-118
lines changed

7 files changed

+160
-118
lines changed

dist/schema-form.js

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -286,24 +286,18 @@ return /******/ (function(modules) { // webpackBootstrap
286286
}
287287
},
288288
condition: function condition(args) {
289+
var strKey = '';
290+
var strModel = 'undefined';
289291
// Do we have a condition? Then we slap on an ng-if on all children,
290292
// but be nice to existing ng-if.
291293
if (args.form.condition) {
292-
var evalExpr = 'evalExpr(' + args.path + '.condition, { model: model, "arrayIndex": $index})';
293294
if (args.form.key) {
294-
var strKey = sfPathProvider.stringify(args.form.key);
295-
var arrayDepth = args.form.key.filter(function (e) {
296-
return e === '';
297-
}).length;
298-
var arrayIndices = arrayDepth > 1 ? Array(arrayDepth - 1).join('$parent.$parent.$parent.') + '$parent.$parent.$index,' : '';
299-
for (var i = arrayDepth; i > 2; i--) {
300-
arrayIndices += Array(i - 1).join('$parent.$parent.$parent.') + '$index,';
301-
}
302-
arrayIndices += '$index';
303-
304-
evalExpr = 'evalExpr(' + args.path + '.condition,{ model: model, "arrayIndex": $index, ' + '"arrayIndices": [' + arrayIndices + '],' + '"modelValue": model' + (strKey[0] === '[' ? '' : '.') + strKey + '})';
295+
strKey = sfPathProvider.stringify(args.form.key);
296+
strModel = 'model' + (strKey[0] === '[' ? '' : '.') + strKey;
305297
}
306298

299+
var evalExpr = 'evalExpr(' + args.path + '.condition, { model: model, ' + '"arrayIndex": $index, ' + '"arrayIndices": arrayIndices, ' + '"path": path, ' + '"$i": $i, ' + '"$index": $index, ' + '"modelValue": ' + strModel + '})';
300+
307301
var children = args.fieldFrag.children || args.fieldFrag.childNodes;
308302
for (var i = 0; i < children.length; i++) {
309303
var child = children[i];
@@ -335,7 +329,7 @@ return /******/ (function(modules) { // webpackBootstrap
335329
state.modelName = 'item';
336330
}
337331

338-
// Flag to the builder that where in an array.
332+
// Flag to the builder that we're in an array.
339333
// This is needed for compatabiliy if a "old" add-on is used that
340334
// hasn't been transitioned to the new builder.
341335
state.arrayCompatFlag = true;
@@ -2702,7 +2696,15 @@ return /******/ (function(modules) { // webpackBootstrap
27022696
if (_angular2.default.isFunction(form.onChange)) {
27032697
form.onChange(ctrl.$modelValue, form);
27042698
} else {
2705-
scope.evalExpr(form.onChange, { 'modelValue': ctrl.$modelValue, form: form });
2699+
scope.evalExpr(form.onChange, {
2700+
"modelValue": ctrl.$modelValue,
2701+
"form": form,
2702+
"arrayIndex": scope.$index,
2703+
"arrayIndices": scope.arrayIndices,
2704+
"path": scope.path,
2705+
"$i": scope.$i,
2706+
"$index": scope.$index
2707+
});
27062708
}
27072709
});
27082710
}
@@ -2757,67 +2759,69 @@ return /******/ (function(modules) { // webpackBootstrap
27572759
});
27582760

27592761
// Fetch our form.
2760-
scope.form = sfSchema.lookup['f' + attrs.sfField];
2762+
scope.initialForm = sfSchema.lookup['f' + attrs.sfField];
2763+
scope.form = _angular2.default.copy(sfSchema.lookup['f' + attrs.sfField]);
27612764
},
27622765
post: function post(scope, element, attrs, ctrl) {
27632766
var sfSchema = ctrl[0];
27642767
var formCtrl = ctrl[1];
27652768
var keyCtrl = ctrl[2];
27662769

2767-
//Keep error prone logic from the template
2768-
scope.showTitle = function () {
2769-
return scope.form && scope.form.notitle !== true && scope.form.title;
2770-
};
2771-
27722770
scope.getKey = function (requiredFormat) {
27732771
var format = requiredFormat || keyFormat.COMPLETE;
27742772
var key = scope.parentKey ? scope.parentKey.slice(0, scope.parentKey.length - 1) : [];
27752773

2776-
if (typeof scope.$index === 'number') {
2777-
key = key.concat(scope.$index);
2778-
};
2774+
// Only calculate completeKey if not already saved to form.key
2775+
if (scope.completeKey !== scope.form.key) {
2776+
if (typeof scope.$index === 'number') {
2777+
key = key.concat(scope.$index);
2778+
};
27792779

2780-
if (scope.form.key && scope.form.key.length) {
2781-
if (typeof key[key.length - 1] === 'number' && scope.form.key.length >= 1) {
2782-
scope.completeKey = key.concat(scope.form.key.slice(-1));
2783-
} else {
2784-
scope.completeKey = scope.form.key.slice();
2780+
if (scope.form.key && scope.form.key.length) {
2781+
if (typeof key[key.length - 1] === 'number' && scope.form.key.length >= 1) {
2782+
scope.completeKey = key.concat(scope.form.key.slice(-1));
2783+
} else {
2784+
scope.completeKey = scope.form.key.slice();
2785+
};
27852786
};
27862787
};
27872788

2789+
// If there is no key then there's nothing to return
27882790
if (!Array.isArray(scope.completeKey)) {
27892791
return undefined;
27902792
};
27912793

2794+
// return the full key if not omiting any types via reduce
27922795
if (format === keyFormat.COMPLETE) {
27932796
return scope.completeKey;
2797+
} else {
2798+
// else to clearly show that data must be ommited
2799+
return scope.completeKey.reduce(function (output, input, i) {
2800+
if (-1 !== [format].indexOf(typeof input === 'undefined' ? 'undefined' : _typeof(input))) {
2801+
return output.concat(input);
2802+
}
2803+
return output;
2804+
}, []);
27942805
};
2795-
2796-
return scope.completeKey.reduce(function (output, input, i) {
2797-
if (-1 !== [format].indexOf(typeof input === 'undefined' ? 'undefined' : _typeof(input))) {
2798-
return output.concat(input);
2799-
}
2800-
return output;
2801-
}, []);
28022806
};
2803-
if (scope.form.key) scope.completeKey = scope.getKey();
2807+
// Now that getKey is defined, run it! ...if there's a key.
2808+
if (scope.form.key) {
2809+
scope.form.key = scope.completeKey = scope.getKey();
2810+
};
28042811

2805-
scope.path = function (modelPath) {
2806-
var i = -1;
2807-
modelPath = modelPath.replace(/\[\]/gi, function (matched) {
2808-
i++;
2809-
return scope.$i[i];
2810-
});
2811-
return scope.$eval(modelPath, scope);
2812+
//Keep error prone logic from the template
2813+
scope.showTitle = function () {
2814+
return scope.form && scope.form.notitle !== true && scope.form.title;
28122815
};
28132816

28142817
//Normalise names and ids
28152818
scope.fieldId = function (prependFormName, omitArrayIndexes) {
2819+
var omit = omitArrayIndexes || false;
28162820
var formName = prependFormName && formCtrl && formCtrl.$name ? formCtrl.$name : undefined;
2817-
var key = scope.getKey();
2821+
var key = scope.completeKey;
28182822

28192823
if (Array.isArray(key)) {
2820-
return sfPath.name(key, '-', formName, omitArrayIndexes);
2824+
return sfPath.name(key, '-', formName, omit);
28212825
} else {
28222826
return '';
28232827
};
@@ -2943,7 +2947,7 @@ return /******/ (function(modules) { // webpackBootstrap
29432947

29442948
// append the field-id to the htmlClass
29452949
scope.form.htmlClass = scope.form.htmlClass || '';
2946-
scope.form.htmlClass += (scope.form.htmlClass ? ' ' : '') + scope.fieldId(false, true);
2950+
scope.form.htmlClass += (scope.form.htmlClass ? ' ' : '') + scope.fieldId(false) + ' ' + scope.fieldId(false, true);
29472951

29482952
var form = scope.form;
29492953

@@ -3428,17 +3432,30 @@ return /******/ (function(modules) { // webpackBootstrap
34283432
return {
34293433
scope: true,
34303434
require: ['^^sfNewArray'],
3431-
link: function link(scope, element, attrs, ctrl) {
3432-
var currentKey = sfPath.parse(attrs.sfParentKey);
3433-
if (currentKey.length > 1) currentKey = currentKey.splice(-1);
3435+
controller: ['$scope', function SFKeyController($scope) {
3436+
this.key = $scope.form && $scope.form.key ? $scope.form.key.splice(0, -2) : [];
3437+
}],
3438+
link: {
3439+
pre: function pre(scope, element, attrs, ctrl) {
3440+
var currentKey = sfPath.parse(attrs.sfParentKey);
3441+
if (currentKey.length > 1) currentKey = currentKey.splice(-1);
34343442

3435-
scope.parentKey = scope.parentKey || [];
3436-
scope.parentKey = scope.parentKey.concat(currentKey, Number(attrs.sfIndex));
3443+
scope.parentKey = scope.parentKey || [];
3444+
scope.parentKey = scope.parentKey.concat(currentKey, Number(attrs.sfIndex));
34373445

3438-
scope.arrayIndex = Number(attrs.sfIndex);
3439-
scope.arrayIndices = scope.arrayIndices || [];
3440-
scope.arrayIndices = scope.arrayIndices.concat(scope.arrayIndex);
3441-
scope.$i = scope.arrayIndices;
3446+
scope.arrayIndex = Number(attrs.sfIndex);
3447+
scope.arrayIndices = scope.arrayIndices || [];
3448+
scope.arrayIndices = scope.arrayIndices.concat(scope.arrayIndex);
3449+
scope.$i = scope.arrayIndices;
3450+
scope.path = function (modelPath) {
3451+
var i = -1;
3452+
modelPath = modelPath.replace(/\[\]/gi, function (matched) {
3453+
i++;
3454+
return '[' + scope.$i[i] + ']';
3455+
});
3456+
return scope.evalExpr(modelPath, scope);
3457+
};
3458+
}
34423459
}
34433460
};
34443461
};

dist/schema-form.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/data/deep-array.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,12 @@
7474
"items": [
7575
{
7676
"key": "users[].comments[].tags[].tag",
77-
"type": "text"
77+
"type": "text",
78+
"onChange": "log(path('model.users[]').name.length)"
7879
},
7980
{
80-
"condition": "model.users[$i[0]].name",
81+
"key": "users[].comments[].tags[].brad",
82+
"condition": "path('model.users[]').name.length",
8183
"type": "string",
8284
"default": "Brad"
8385
}

src/directives/changed.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@ export default function() {
2121
if (angular.isFunction(form.onChange)) {
2222
form.onChange(ctrl.$modelValue, form);
2323
} else {
24-
scope.evalExpr(form.onChange, { 'modelValue': ctrl.$modelValue, form: form });
24+
scope.evalExpr(form.onChange, {
25+
"modelValue": ctrl.$modelValue,
26+
"form": form,
27+
"arrayIndex": scope.$index,
28+
"arrayIndices": scope.arrayIndices,
29+
"path": scope.path,
30+
"$i": scope.$i,
31+
"$index": scope.$index
32+
});
2533
}
2634
});
2735
}

src/directives/field.js

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,68 +30,71 @@ sfPath, sfSelect) {
3030
});
3131

3232
// Fetch our form.
33-
scope.form = sfSchema.lookup['f' + attrs.sfField];
33+
scope.initialForm = sfSchema.lookup['f' + attrs.sfField];
34+
scope.form = angular.copy(sfSchema.lookup['f' + attrs.sfField]);
3435
},
3536
post: function(scope, element, attrs, ctrl) {
3637
var sfSchema = ctrl[0];
3738
var formCtrl = ctrl[1];
3839
var keyCtrl = ctrl[2];
3940

40-
//Keep error prone logic from the template
41-
scope.showTitle = function() {
42-
return scope.form && scope.form.notitle !== true && scope.form.title;
43-
};
44-
4541
scope.getKey = function(requiredFormat) {
4642
let format = requiredFormat || keyFormat.COMPLETE;
4743
let key = (scope.parentKey) ? scope.parentKey.slice(0, scope.parentKey.length-1) : [] ;
4844

49-
if (typeof scope.$index === 'number') {
50-
key = key.concat(scope.$index);
51-
};
45+
// Only calculate completeKey if not already saved to form.key
46+
if(scope.completeKey !== scope.form.key) {
47+
if (typeof scope.$index === 'number') {
48+
key = key.concat(scope.$index);
49+
};
5250

53-
if(scope.form.key && scope.form.key.length) {
54-
if(typeof key[key.length-1] === 'number' && scope.form.key.length >= 1) {
55-
scope.completeKey = key.concat(scope.form.key.slice(-1));
56-
}
57-
else {
58-
scope.completeKey = scope.form.key.slice();
51+
if(scope.form.key && scope.form.key.length) {
52+
if(typeof key[key.length-1] === 'number' && scope.form.key.length >= 1) {
53+
scope.completeKey = key.concat(scope.form.key.slice(-1));
54+
}
55+
else {
56+
scope.completeKey = scope.form.key.slice();
57+
};
5958
};
6059
};
6160

61+
// If there is no key then there's nothing to return
6262
if(!Array.isArray(scope.completeKey)) {
6363
return undefined;
6464
};
6565

66+
// return the full key if not omiting any types via reduce
6667
if (format === keyFormat.COMPLETE) {
6768
return scope.completeKey;
69+
}
70+
else {
71+
// else to clearly show that data must be ommited
72+
return scope.completeKey.reduce((output, input, i) => {
73+
if (-1 !== [ format ].indexOf((typeof input))) {
74+
return output.concat(input);
75+
}
76+
return output;
77+
}, []);
6878
};
69-
70-
return scope.completeKey.reduce((output, input, i) => {
71-
if (-1 !== [ format ].indexOf((typeof input))) {
72-
return output.concat(input);
73-
}
74-
return output;
75-
}, []);
7679
};
77-
if(scope.form.key) scope.completeKey = scope.getKey();
80+
// Now that getKey is defined, run it! ...if there's a key.
81+
if(scope.form.key) {
82+
scope.form.key = scope.completeKey = scope.getKey();
83+
};
7884

79-
scope.path = function(modelPath) {
80-
var i = -1;
81-
modelPath = modelPath.replace(/\[\]/gi, function(matched){
82-
i++;
83-
return scope.$i[i];
84-
});
85-
return scope.$eval(modelPath, scope);
86-
}
85+
//Keep error prone logic from the template
86+
scope.showTitle = function() {
87+
return scope.form && scope.form.notitle !== true && scope.form.title;
88+
};
8789

8890
//Normalise names and ids
8991
scope.fieldId = function(prependFormName, omitArrayIndexes) {
92+
let omit = omitArrayIndexes || false;
9093
let formName = (prependFormName && formCtrl && formCtrl.$name) ? formCtrl.$name : undefined;
91-
let key = scope.getKey();
94+
let key = scope.completeKey;
9295

9396
if(Array.isArray(key)) {
94-
return sfPath.name(key, '-', formName, omitArrayIndexes);
97+
return sfPath.name(key, '-', formName, omit);
9598
}
9699
else {
97100
return '';
@@ -227,7 +230,7 @@ sfPath, sfSelect) {
227230

228231
// append the field-id to the htmlClass
229232
scope.form.htmlClass = scope.form.htmlClass || '';
230-
scope.form.htmlClass += (scope.form.htmlClass ? ' ' : '') + scope.fieldId(false, true);
233+
scope.form.htmlClass += (scope.form.htmlClass ? ' ' : '') + scope.fieldId(false) + ' ' + scope.fieldId(false, true);
231234

232235
var form = scope.form;
233236

src/directives/keyController.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,30 @@ export default function(schemaForm, sfPath) {
55
return {
66
scope: true,
77
require: ['^^sfNewArray'],
8-
link: function(scope, element, attrs, ctrl) {
9-
var currentKey = sfPath.parse(attrs.sfParentKey);
10-
if(currentKey.length > 1) currentKey = currentKey.splice(-1);
8+
controller: ['$scope', function SFKeyController($scope) {
9+
this.key = ($scope.form && $scope.form.key) ? $scope.form.key.splice(0, -2) : [];
10+
}],
11+
link: {
12+
pre: function(scope, element, attrs, ctrl) {
13+
var currentKey = sfPath.parse(attrs.sfParentKey);
14+
if(currentKey.length > 1) currentKey = currentKey.splice(-1);
1115

12-
scope.parentKey = scope.parentKey || [];
13-
scope.parentKey = scope.parentKey.concat(currentKey, Number(attrs.sfIndex));
16+
scope.parentKey = scope.parentKey || [];
17+
scope.parentKey = scope.parentKey.concat(currentKey, Number(attrs.sfIndex));
1418

15-
scope.arrayIndex = Number(attrs.sfIndex);
16-
scope.arrayIndices = scope.arrayIndices || [];
17-
scope.arrayIndices = scope.arrayIndices.concat(scope.arrayIndex);
18-
scope.$i = scope.arrayIndices;
19+
scope.arrayIndex = Number(attrs.sfIndex);
20+
scope.arrayIndices = scope.arrayIndices || [];
21+
scope.arrayIndices = scope.arrayIndices.concat(scope.arrayIndex);
22+
scope.$i = scope.arrayIndices;
23+
scope.path = function(modelPath) {
24+
var i = -1;
25+
modelPath = modelPath.replace(/\[\]/gi, function(matched){
26+
i++;
27+
return '[' + scope.$i[i] + ']';
28+
});
29+
return scope.evalExpr(modelPath, scope);
30+
}
31+
}
1932
}
2033
};
2134
};

0 commit comments

Comments
 (0)