-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: