ember-cp-validations
ember-cp-validations copied to clipboard
Disabled check not recomputing immediately on some attributes
Environment
- Ember Version: 3.0.0
- Ember CLI Version: 3.0.0
- Ember CP Validations Version: 3.5.1
Steps to Reproduce
I noticed that for my custom validator, it wasn't quite working correctly, the disabled check was being cached or something - let me explain.
Validator
// Use this validator to determine if datetime in model is before given compare date
const IsBeforeCheck = BaseValidator.extend({
validate(value, options, model, attribute) {
/* Some custom validation code here */
return isValid ? isValid : this.createErrorMessage('error message etc.', value, options);
}
});
IsBeforeCheck.reopenClass({
getDependentsFor(attribute, options) {
return [];
}
});
export default IsBeforeCheck;
Model
'scheduledTime': {
validators: [
validator('isBefore', {
compareDate: computed('model.reportParams.endDate',(edt) => edt),
disabled: computed('model.reportType','model.reportParams.isDateRange', function() {
let reportType = this.get('model.reportType');
let isDateRange = this.get('model.reportParams.isDateRange');
let result = false;
if(reportType === 'tpms_current_status') result = result || true;
if(!isDateRange) result = result || true;
console.log(result);
return result;
}),
dependentKeys: [
'model.reportType',
'model.reportParams.isDateRange',
'model.reportParams.endDate'
],
})
]
},
NOTE: I also have a global debounce value set to 500 - but I tried setting this to 0 and it didn't fix anything.
With the code above, I noticed that if I changed the isDateRange
flag, or modified the endDate
, the validator would fire correctly and disabled would be correctly set. But if I changed the reportType
, the validator was doing strange things.
The only way the reportType
is set is via the template on button click, eg {{action (mut model.reportType) 'tpms_current_status'}}
The validator would correctly detect that the reportType
changed and that re-validation needed to happen, but it didn't necessarily have the correct option values. Basically, when disabled should have returned true, it would return false, and vise versa.
I narrowed it down to this;
- If I set reportType to tpms_current_status so that disabled should return TRUE, at this point in the code, disabled incorrectly returns false and continues with the validation (it doesn't even try to call the disabled CP, just gets a cached value) https://github.com/offirgolan/ember-cp-validations/blob/d4e720dbb2fef38b996a45357a446b67a4e672ba/addon/validations/factory.js#L503-L509
- But by this point in the code, disabled does have the correct value - but there is no disabled check here, so it continues with the validation anyway https://github.com/offirgolan/ember-cp-validations/blob/d4e720dbb2fef38b996a45357a446b67a4e672ba/addon/validations/factory.js#L522
Anyone know what's going on here? Am I doing something wrong? It works most other times I've used it, I can't figure out why this is any different
@Techn1x it seems like the issue is with your disabled
CP. Looks like the dependent keys dont match the properties you are accessing so it doesnt recompute. Can you try the following:
'scheduledTime': {
validators: [
validator('isBefore', {
compareDate: computed('model.reportParams.endDate',(edt) => edt),
disabled: computed('model.reportType', 'model.reportParams.isDatePeriodDateRange', function() {
let reportType = this.get('model.reportType');
let isDateRange = this.get('model.reportParams.isDatePeriodDateRange');
let result = false;
if(reportType === 'tpms_current_status') result = result || true;
if(!isDateRange) result = result || true;
console.log(result);
return result;
})
})
]
}
Sorry, that was a typo, I've edited my original post to reflect the correct variable. Issue still stands though.
From what I can tell, it seems that the dependentKeys are working correctly (so attempting to revalidate the property when they change) - but the disabled CP is being cached for some reason
I am running into the same issue. In my example below, the debugger is firing on first load and then whenever the watched property dayMode
is changing from false to true, but not when going from true to false. This effectively means that the validator is never disabled.
myProperty: validator('number',
integer: true
allowString: true
disabled: Ember.computed('model.dayMode', ->
debugger
not @get('model.dayMode')
)
)
I was able to make it recompute every time by using a workaround and tagging the CP as volatile, but I don't think that should be necessary.
myProperty: validator('number',
integer: true
allowString: true
disabled: Ember.computed('model.dayMode', ->
debugger
not @get('model.dayMode')
).volatile()
)
Thanks for that @mriska glad I am not alone here :p I faced this issue again today with a different custom validator, a workaround I have found is to define disabled
as something like;
disabledComputed: computed( .... )
Then in your custom validator, at the top, something like;
const IsBeforeCheck = BaseValidator.extend({
validate(value, options, model, attribute) {
if(options.disabledComputed) return true;
/* more validation code */
}
);
This way you're just using your own attribute and whatever problem there is with specifically setting disabled
goes away.
I am also seeing this issue and have confirmed that @mriska 's fix works. So, to clarify, this is part of a multi-step form wizard with next and back buttons. model.isBusinessInfoStep is getting correctly updated between steps, but it doesn't seem to trigger the "disabled" property. In this particular case, the validations work if you only click next, but going back and then forward again causes the wrong validations to trigger because "disabled" is not updated.
This doesn't work:
'contact.address1': [
validator('presence', {
presence: true,
disabled: not('model.isBusinessInfoStep'),
message: 'Please enter your street address.'
})
],
And this does work:
'contact.address1': [
validator('presence', {
presence: true,
disabled: not('model.isBusinessInfoStep').volatile(),
message: 'Please enter your street address.'
})
],
Im not able to recreate this issue in a twiddle. Am I missing anything in that example?
I tried to re-create it in a twiddle with no success. I now believe it has something to do with ember-bootstrap-cp-validations but can't get ember-bootstrap to load in the twiddle. Here's what I tried:
Note that it may not be the optimal way to build something but I was trying to pseudo replicate my situation without all the complexity.
https://ember-twiddle.com/f43cad40d4ca8d95a94549840821373c
The project were I am seeing this error does not include ember-bootstrap-cp-validations
, so it can't be the sole trigger at least.
So I was hit by something similar wherein I thought the bug must be in ember-cp-validations
With further digging though, I found that the CPs
aren't recalculating for some reason.
I was able to reproduce it with a Twiddle.
Background info on Stack overflow
Twiddle reproduction (go to the route /my-route
)
The issue I faced was due to adding volatile
on the CPs
https://github.com/emberjs/ember.js/issues/17037
That would explain why the disabled
CP wasn't recomputing as the thing it was depending on was marked volatile
Version 3.5.4 still same problem: https://github.com/offirgolan/ember-cp-validations/issues/596#issuecomment-407068990
I encounter the same problem. volatile()
works as a workaround but its deprecated so it's not an option.
Also from what I noticed while playing around with this setup - if I define a disabled
property I (like many of you) define it as a not
alias. But, if I substitute it with readOnly
the behaviour of validation, of course, flips over BUT the issue with caching disappears.