Skip to content
Permalink
Browse files

feat(field): recompute optional property on value or hidden changes

  • Loading branch information...
anehx authored and czosel committed May 27, 2019
1 parent 3fc5aa4 commit fd18d4354e62c41730c85dc997e664bcb4bac052
Showing with 64 additions and 28 deletions.
  1. +15 −6 addon/lib/field.js
  2. +33 −16 addon/lib/question.js
  3. +16 −6 tests/unit/lib/question-test.js
@@ -117,7 +117,7 @@ export default EmberObject.extend(Evented, {

this.setProperties({
_errors: [],
dependentFields: [],
dependentFields: { isRequired: [], isHidden: [] },
question,
answer
});
@@ -136,13 +136,22 @@ export default EmberObject.extend(Evented, {
}).readOnly(),

updateHidden: on("valueChanged", "hiddenChanged", function() {
this.dependentFields.forEach(field => field.question.hiddenTask.perform());
this.dependentFields.isHidden.forEach(field =>
field.question.hiddenTask.perform()
);
}),

registerDependentField(field) {
if (!this.dependentFields.find(f => f.id === field.id)) {
this.dependentFields.push(field);
}
updateOptional: on("valueChanged", "hiddenChanged", function() {
this.dependentFields.isRequired.forEach(field =>
field.question.optionalTask.perform()
);
}),

registerDependentField(field, key) {
this.set(`dependentFields.${key}`, [
...new Set(this.get(`dependentFields.${key}`)),
field
]);
},

/**
@@ -33,20 +33,28 @@ export default EmberObject.extend({
* @property {String[]} dependsOn
* @accessor
*/
dependsOn: computed("isHidden", function() {
const dependents = [
...new Set(
getTransforms(getAST(this.isHidden))
.filter(transform => transform.name === "answer")
.map(transform => transform.subject.value)
)
];
dependsOn: computed("isHidden", "isRequired", function() {
const keys = ["isHidden", "isRequired"];

return dependents.map(slugWithPath => {
const field = this.document.findField(slugWithPath);
field.registerDependentField(this.field);
return field;
});
return keys.reduce((obj, key) => {
const dependents = [
...new Set(
getTransforms(getAST(this[key]))
.filter(transform => transform.name === "answer")
.map(transform => transform.subject.value)
)
];

return Object.assign(obj, {
[key]: dependents.map(slugWithPath => {
const field = this.document.findField(slugWithPath);

field.registerDependentField(this.field, key);

return field;
})
});
}, {});
}).readOnly(),

/**
@@ -61,8 +69,8 @@ export default EmberObject.extend({
*/
hiddenTask: task(function*() {
let hidden =
this.dependsOn.length &&
this.dependsOn.every(
this.dependsOn.isHidden.length &&
this.dependsOn.isHidden.every(
field =>
field.question.hidden ||
(field.question.__typename !== "TableQuestion" &&
@@ -97,6 +105,15 @@ export default EmberObject.extend({
* @return {Boolean}
*/
optionalTask: task(function*() {
return !(yield this.document.questionJexl.eval(this.isRequired));
const hidden =
this.dependsOn.isRequired.length &&
this.dependsOn.isRequired.every(
field =>
field.question.hidden ||
(field.question.__typename !== "TableQuestion" &&
(field.answer.value === null || field.answer.value === undefined))
);

return hidden || !(yield this.document.questionJexl.eval(this.isRequired));
})
});
@@ -67,20 +67,29 @@ module("Unit | Library | question", function(hooks) {
"question2.isHidden",
"'question1'|answer > 9000 && 'question3'|doesntexist == 'blubb'"
);
assert.expect(2);
assert.equal(this.question2.dependsOn.length, 1);
this.set("question2.isRequired", "'question1'|answer < 3");

assert.expect(4);
assert.equal(this.question2.dependsOn.isHidden.length, 1);
assert.equal(this.question2.dependsOn.isRequired.length, 1);
assert.equal(
this.question2.dependsOn[0].id,
this.question2.dependsOn.isHidden[0].id,
"Document:1:Question:question1"
);
assert.equal(
this.question2.dependsOn.isRequired[0].id,
"Document:1:Question:question1"
);

this.set("question2.isHidden", "false");
this.set("question2.isRequired", "false");
});

test("dependsOn only contains existing questions", async function(assert) {
this.set("question2.isHidden", "'question-nonexistent'|answer > 9000");
assert.expect(1);
assert.throws(
() => this.question2.dependsOn,
() => this.question2.dependsOn.isHidden,
/Question could not be resolved: "question-nonexistent". Available: "question1", "question2"/
);
this.set("question2.isHidden", "false");
@@ -91,9 +100,10 @@ module("Unit | Library | question", function(hooks) {
"question2.isHidden",
"'question1'|answer > 9000 && 'question1'|answer < 10000"
);

assert.expect(1);
assert.deepEqual(
this.question2.dependsOn.map(field => field.question.slug),
this.question2.dependsOn.isHidden.map(field => field.question.slug),
["question1"]
);
this.set("question2.isHidden", "false");
@@ -108,7 +118,7 @@ module("Unit | Library | question", function(hooks) {
);
assert.expect(1);
assert.deepEqual(
ba1.dependsOn.map(
ba1.dependsOn.isHidden.map(
field => `${field.document.raw.form.slug} > ${field.question.slug}`
),
["a-a > a-a-1", "a-b > a-a-1"]

0 comments on commit fd18d43

Please sign in to comment.
You can’t perform that action at this time.