I have two select lists, where on depends on the other. The issue I am having is the choices function on the 2nd property is being executed before the 1st property's onSetValue function has completed. I would think the dependsOn relationship would make sure the 1st property's value is set before running a dependancy's choices function.
Here are some relevant code snippets and a codesandbox link.
Thank you
JavaScriptSurvey.Serializer.addProperty("survey", {
name: "region",
category: "Geo Location",
categoryIndex: 1,
onSetValue: async (obj, value, jsonConverter) => {
console.log("region onSetValue START");
console.log("before sleep");
await sleep(2000);
console.log("after sleep");
console.log("region onSetValue END");
return value;
},
choices: ["Africa", "Americas", "Asia", "Europe", "Oceania"]
});
Survey.Serializer.addProperty("survey", {
name: "country",
category: "Geo Location",
dependsOn: ["region"],
onSetValue: (obj, value, jsonConverter) => {
console.log("country onSetValue START");
},
choices: function (obj, choicesCallback) {
console.log("country choices fn called"); // shouldn't this be called after a dependsOn onSetValue?
}
});
I would expect "country choices fn called" between the two sleep log entries to be the last log entry.
(using async/await)
https://codesandbox.io/s/nervous-solomon-bp15gg?file=/src/index.js
(using promise chains)
https://codesandbox.io/s/festive-volhard-endvin?file=/src/index.js
Hello Paul,
Thank you for sharing these samples. The country's
choices
function is called after the region's property is set if the asynchronoussleep
function is not executed.Survey.Serializer.addProperty("survey", { name: "region", category: "Geo Location", categoryIndex: 1, onSetValue: async (obj, value, jsonConverter) => { console.log("region onSetValue START"); console.log("before sleep"); //await sleep(2000); console.log("after sleep"); console.log("region onSetValue END"); return value; }, choices: ["Africa", "Americas", "Asia", "Europe", "Oceania"] }); Survey.Serializer.addProperty("survey", { name: "country", category: "Geo Location", dependsOn: ["region"], onSetValue: (obj, value, jsonConverter) => { console.log("country onSetValue START"); }, choices: function (obj, choicesCallback) { console.log("country choices fn called"); // shouldn't this be called after a dependsOn onSetValue? } });
I got the following console output by executing the code above:
region onSetValue START before sleep after sleep region onSetValue END country choices fn called
Would you please clarify whether you experience any difficulties? Do you wish to execute an asynchronous call in the first property's
onSetValue
function?I look forward to your reply.
Yes, I do wish to execute the async call first in the
onSetValue
function. We want to execute a 3rd party service to set a value before the dependent choices function fires. -PaulHello Paul,
Thank you for the clarification.
The thing is that the onSetValue function is called after a property was set. That is, it doesn't wait until you manually set a property value. Instead, it is raised when a user changes the property; after that, all dependable properties are updated without waiting until an asynchronous operation is executed.
One more note: to set a region property value in the
onSetValue
event handler, it's necessary to use theobj.setPropertyValue("region", value)
.I'll reach out to the development team and discuss what is the best option to retrieve a property value using an async function call and update the dependent property's choices. I'll drop a line once I have any news to share.
Thank you Jane, I appreciate the information and await an update.
For those following, I updated my sample and here is the output, as you can see the onSetValue function doesn't wait for the continuation.
Survey.Serializer.addProperty("survey", { name: "region", category: "Geo Location", categoryIndex: 1, onSetValue: async (obj, value, jsonConverter) => { console.log("region onSetValue START"); console.log("before sleep"); await sleep(2000); console.log("after sleep"); console.log("before setPropertyValue"); obj.setPropertyValue("region", value); console.log("after setPropertyValue"); console.log("region onSetValue END"); return value; }, choices: ["Africa", "Americas", "Asia", "Europe", "Oceania"] });
https://codesandbox.io/s/proud-lake-qdy2zf?file=/src/index.js
Hello Paul,
Thank you for the update. After a
Region
property was set, call the updateDynamicProperties function to update aCountry
property editor:let countryPropEditor = undefined; ... Survey.Serializer.addProperty("survey", { name: "region", category: "Geo Location", categoryIndex: 1, onSetValue: async (obj, value, jsonConverter) => { await sleep(2000); obj.setPropertyValue("region", value); if (countryPropEditor) { countryPropEditor.updateDynamicProperties(); } return value; }, choices: ["Africa", "Americas", "Asia", "Europe", "Oceania"] }); Survey.Serializer.addProperty("survey", { name: "country", category: "Geo Location", dependsOn: ["region"], onSetValue: (obj, value, jsonConverter) => { ... }, choices: function (obj, choicesCallback) { ... }, onPropertyEditorUpdate: (obj, editor) => { countryPropEditor = editor; } });
The updated example: https://codesandbox.io/s/cocky-chatelet-5ulx2d?file=/src/index.js:338-1119.
Please let me know if this does the trick.
Thanks Jane, we'll take it in-house and see if this works for us. -Paul
Thank you for the update, Paul. Please feel free to share your results with us.