Skip to content
This repository was archived by the owner on Apr 30, 2018. It is now read-only.

Commit 2073a91

Browse files
pseudo-suKent C. Dodds
authored and
Kent C. Dodds
committedJul 26, 2016
feat(formly-form): formlyField.runExpressions resolve after fields set
* feat(formly-form): formlyField.runExpressions resolve after fields set * test(formly-form): ensure expressions finish before validators run
1 parent a4c54bb commit 2073a91

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed
 

Diff for: ‎src/directives/formly-field.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,25 @@ function formlyField($http, $q, $compile, $templateCache, $interpolate, formlyCo
5959

6060
// function definitions
6161
function runExpressions() {
62+
const deferred = $q.defer()
6263
// must run on next tick to make sure that the current value is correct.
63-
return $timeout(function runExpressionsOnNextTick() {
64+
$timeout(function runExpressionsOnNextTick() {
65+
const promises = []
6466
const field = $scope.options
6567
const currentValue = valueGetterSetter()
6668
angular.forEach(field.expressionProperties, function runExpression(expression, prop) {
6769
const setter = $parse(prop).assign
6870
const promise = $q.when(formlyUtil.formlyEval($scope, expression, currentValue, currentValue))
69-
promise.then(function setFieldValue(value) {
70-
setter(field, value)
71-
})
71+
.then(function setFieldValue(value) {
72+
setter(field, value)
73+
})
74+
promises.push(promise)
75+
})
76+
$q.all(promises).then(function() {
77+
deferred.resolve()
7278
})
7379
}, 0, false)
80+
return deferred.promise
7481
}
7582

7683
function watchExpressions() {

Diff for: ‎src/directives/formly-form.test.js

+43
Original file line numberDiff line numberDiff line change
@@ -1314,4 +1314,47 @@ describe('formly-form', () => {
13141314
})
13151315
})
13161316
})
1317+
describe('extras', () => {
1318+
describe('validateOnModelChange', () => {
1319+
it('should run validators after expressions are set', () => {
1320+
let inputs, invalidInputs, el
1321+
1322+
scope.model = {
1323+
foo: null,
1324+
bar: 123,
1325+
}
1326+
1327+
scope.fields = [
1328+
{template: input, key: 'foo', extras: {validateOnModelChange: true}},
1329+
{template: input, key: 'bar', templateOptions: {type: 'number'}},
1330+
]
1331+
// First Field isn't valid when second field is 1
1332+
scope.fields[0].expressionProperties = {
1333+
'templateOptions.isValid': 'model.bar !== 1',
1334+
}
1335+
// validator to use isValid attribute
1336+
scope.fields[0].validators = {isValid: {expression: (viewValue, modelValue, fieldScope) => {
1337+
return fieldScope.to.isValid
1338+
}}}
1339+
1340+
el = compileAndDigest()
1341+
1342+
// Input state before
1343+
inputs = el[0].querySelectorAll('input')
1344+
invalidInputs = el[0].querySelectorAll('input.ng-invalid')
1345+
expect(inputs.length).to.equal(2)
1346+
expect(invalidInputs.length).to.equal(0)
1347+
1348+
// Enter '1' into second field
1349+
angular.element(inputs[1]).val(1).triggerHandler('change')
1350+
$timeout.flush()
1351+
1352+
// Input state after
1353+
inputs = el[0].querySelectorAll('input')
1354+
invalidInputs = el[0].querySelectorAll('input.ng-invalid')
1355+
expect(inputs.length).to.equal(2)
1356+
expect(invalidInputs.length).to.equal(1)
1357+
})
1358+
})
1359+
})
13171360
})

0 commit comments

Comments
 (0)