poteto / ember-changeset-validations

Validations for ember-changeset

Home Page:http://bit.ly/ember-changeset-demo

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

building validations programmatically from a parent model

muziejus opened this issue · comments

This is more like a 🤔 , since I solved how to get around it. I tried very hard to tweak the demo twiddle to reproduce this, but it just keeps crashing for different reasons.

I have a data structure of Texts, and each Text has multiple Entrys [sic]. Now, since each Text has different requirements of its Entrys, the model has an array, entryProperties, that looks like, say, this:

// inside a createRecord("text", {...
entryProperties: [ { name: "page", type: "number" }, {name: "speaker", type: "string" }]

These all get saved under the umbrella of properties in the Entry model, so a typical Entry will look something like this:

{ id: "blah", name: "foo", properties: { page: 234, speaker: "narrator" }}

so since the validation scheme of an Entry's properties object is set at the Text level, I can't write a fixed Validations file in app/validations or whatever. Here's where things get weird...

In the component setting up the form, this works fine:

// inside a Component definition
get EntryValidations() {
  return {
    name: validatePresence(true),
    "properties.page": validateNumber(true),
    "properties.speaker": validatePresence(true)
  };
}

And then even this works fine:

// inside a Component definition
get EntryValidations() {
  const validations = { name: validatePresence(true) };
  [{name: "page", type: "number"}, {name: "speaker", type: "string"}].forEach( prop => {
  if(prop.type === "number") {
    validations[`properties.${prop.name}`] = validateNumber(true);
  } else {
    validations[`properties.${prop.name}`] = validatePresence(true);
  }

  return validations;
}

But this causes any number of problems, most notably that the "name" <input> wouldn't even update when I type in it. Here I'm passing a Text in as this.args.model:

// inside a Component definition
get EntryValidations() {
  const validations = { name: validatePresence(true) };
  this.args.model.entryProperties.forEach( prop => {
  if(prop.type === "number") {
    validations[`properties.${prop.name}`] = validateNumber(true);
  } else {
    validations[`properties.${prop.name}`] = validatePresence(true);
  }

  return validations;
}

In the console, the validations object would look identical to the previous examples, but it just caused chaos. No amount of .toArray() or [ ...this.args.model.entryProperties] inside the get EntryValidations() would fix it. Finally, on a lark, I tried this, and it worked:

// inside a Component definition
entryProperties = this.args.model.entryProperties.toArray();
get EntryValidations() {
  const validations = { name: validatePresence(true) };
  this.entryProperties.forEach( prop => {
  if(prop.type === "number") {
    validations[`properties.${prop.name}`] = validateNumber(true);
  } else {
    validations[`properties.${prop.name}`] = validatePresence(true);
  }

  return validations;
}

All is good, but this seems like a weird hiccup?