Ember Changeset Nested Validations

Last reviewed on April 8, 2023

Ember Changeset supports nested data. This is documented on the repo. For example:

const changeset = new Changeset({
  name: {
    first: "David",
    last: "Tang",
  },
});

changeset.set("name.first", "D");
changeset.set("name.last", "T");

console.log(changeset.changes);
// [
//   {
//     key: 'name.first',
//     value: 'D',
//   },
//   {
//     key: 'name.last',
//     value: 'T',
//   },
// ];

changeset.save();

console.log(changeset.data);
// {
//   name: {
//     first: 'D',
//     last: 'T',
//   },
// };

However, what isn't documented at the time of this writing is that validations using the companion library Ember Changeset Validations can also be nested to match the structure of the data. For example:

const validationMap = {
  name: {
    first: [validatePresence(true)],
    last: [validatePresence(true)],
  },
};

const changeset = new Changeset(
  {
    name: {
      first: "David",
      last: "Tang",
    },
  },
  lookupValidator(validationMap),
  validationMap
);

changeset.validate();

console.log(changeset.errors);
// []

changeset.set("name.first", "");
changeset.set("name.last", "");
changeset.validate();

console.log(changeset.errors);
// [
//   {
//     key: 'name.first',
//     validation: ["Name first can't be blank"],
//     value: '',
//   },
//   {
//     key: 'name.last',
//     validation: ["Name last can't be blank"],
//     value: '',
//   },
// ];

The above was tested with the following package versions:

package.json
{
  "devDependencies": {
    "ember-changeset": "^4.1.2",
    "ember-changeset-validations": "^4.1.1"
  }
}