-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Validations with dependentKeys do not work with change-set changes. #25
Comments
I encountered this same need tonight. Following on @arenoir's idea, I was able to come up with something that works (with a minor change to ember-changeset). I made a // ValidationProxy acts as a proxy between a model and ember-changeset-cs-validations.
const ValidationProxy = EmberObject.extend({
_content: null,
_changes: null,
init() {
this._super(...arguments);
this._changes = {};
},
unknownProperty(key) {
if (this._changes.hasOwnProperty(key)) {
return this._changes[key];
}
return get(this, `_content.${key}`);
},
setUnknownProperty(key, value) {
if (key === "_content") {
this._content = value;
return;
}
this._changes[key] = value;
this.notifyPropertyChange(key);
},
_performRollback() {
let keysToReset = Object.keys(this._changes);
this._changes = {};
keysToReset.forEach(key => this.notifyPropertyChange(key));
},
}); This proxy is like a mini changeset of its own. It proxies property So I might have a validation class like this: export const ProductValidations = buildValidations({
name: validator("presence", { presence: true, description: "Name" }),
});
const ProductValidation = ValidationProxy.extend(ProductValidations);
export default ProductValidation; In order to make this work, I've had to make an alternate changeset creation method which takes two arguments: the model, and an instance of the validations proxy (that's already set up with a reference to the model): export function createValidatedChangeset(model, validation) {
let validationMap = validation
.get("validations.validatableAttributes")
.reduce((o, attr) => {
o[attr] = true;
return o;
}, {});
let validateFn = function({ key, newValue }) {
// set the property immediately on the proxy so it is available to other validations:
validation.set(key, newValue);
return validation
.validateAttribute(key, newValue)
.then(({ validations }) => {
return validations.get("isValid") ? true : validations.get("message");
});
};
let cs = new Changeset(model, validateFn, validationMap);
cs.on("afterRollback", () => validation._performRollback());
return cs;
} Now I can set this up with: product = {}; // my model object
// validation instance, created with an owner inside tests:
let validation = ProductValidation.create(this.owner.ownerInjection(), {
_content: product,
});
// or, inside my form component:
let validation = getOwner(this)
.factoryFor(`validation:${validationName}`)
.create({ _content: model });
changeset = createValidatedChangeset(product, validation); Now, I can get the best of both worlds: the full benefits of ember-changeset (especially the ability to validate properties dependent on the proposed/chantged value of other properties), and also all the niceties of ember-cp-validations: full access to the object model, including services. I'm not sure if there's a super straightforward way to make this into a good general purpose PR. In the mean time I've posted it here to help others. |
Thanks @bgentry! This will help get me unstuck. I know this issue is a little old, are you still using this approach today? |
IMO the best feature of the cp-validations addon is the ability to conditionally validate attributes based on other attribute values. This feature is lost when the validate function is built. I am thinking a separate Object needs to be created with the validations and all changes applied to it within the validate function.
Something like:
The text was updated successfully, but these errors were encountered: