Do not call external Data Manager.set External Data while rendering
The ExternalDataManager is deprecated, please use the addExternalValue API.
This error occurs if the external
To solve this error, consider why you are calling set
. If the result of the data being set represents a default value, the object or widget could treat the absence of the value as if that default value was set. If the external value is the result of an expensive computation, make sure that any call to set
happens asynchronously so it will never coincide with rendering.
JavaScript
import externalDataManager from 'fontoxml-templated-views/src/externalDataManager.js';
// Wrong: do not modify external data while rendering
function renderCustomWidget(sourceNode, renderer) {
let externalValue = sourceNode.getExternalValue('my-external-value');
if (externalValue === undefined) {
// Value is missing, initialize
externalValue = 'initial-value';
externalDataManager.setExternalData('my-external-value', externalValue);
}
return ['span', externalValue];
}
// Solution 1: treat undefined as the initial value
function renderCustomWidget(sourceNode, renderer) {
let externalValue = sourceNode.getExternalValue('my-external-value');
if (externalValue === undefined) {
// Value is missing, use initial value
externalValue = 'initial-value';
}
return ['span', externalValue];
}
// Solution 2: ensure set happens elsewhere, asynchronously
function renderCustomWidget(sourceNode, renderer) {
let externalValue = sourceNode.getExternalValue('my-external-value');
if (externalValue === undefined) {
// Value is missing, use fallback value
externalValue = 'fallback-value';
}
return ['span', externalValue];
}
// Somewhere else:
computeExternalValue().then(value => {
externalDataManager.setExternalData('my-external-value', value);
});
// Solution 3 or temporary work-around: force the call to be async using setTimeout
// Note that the other solutions are preferred, as this approach will cause an unnecessary view update.
function renderCustomWidget(sourceNode, renderer) {
let externalValue = sourceNode.getExternalValue('my-external-value');
if (externalValue === undefined) {
// Value is missing, initialize
externalValue = 'fallback-value';
setTimeout(() => {
externalDataManager.setExternalData('my-external-value', 'initial-value');
}, 0);
}
return ['span', externalValue];
}
The following example shows a typical instance of code causing this problem, as well as several potential solutions:
Refer to the guide on custom XPath/XQuery invalidation for more information on how to expose external data to XPath using add
.
If your application uses private API to invalidate a custom XPath function, you may see a different error message: "Can not invalidate external dependency while computing."
The cause is the same as the error above, and similar solutions can be applied.