Dynamically include components in model processors
Current Behavior
- All components in the model are processed sequentially
- After model processing is completed the system moves on to rendering
Issue: there’s no easy way to have a model processor dynamically add new components to the overall model and include them for processing. Instead, the model processors for the dynamic have to be invoked manually.
New Behavior
- All components in the model are processed sequentially
- Any components that are dynamically added to the model are processed in the order they were added. These can in turn add new components to the model.
- After model processing is completed the system moves on to rendering
Implementation
Expose two new utility function called componentInclude
and componentTemplate
that allow model processors to dynamically, synchronously add new components to the model.
componentInclude
$.componentInclude(targetPath, rawModel)
Description
Dynamically adds the provided rawModel
to the model for the current component. It will be added at the location specified by targetPath
. The rawModel is scanned for resource types (just as the initial raw Sling data is) and all components found in the rawModel
are added to the queue of models to be processed. The addition of the rawModel
to the overall model is synchronous. The model processing for all the components then falls into the same asynchronous list being processed for the overall model.
Components that are in the initial model are guaranteed to be model processed before any dynamic ones. Dynamic ones are processed in the order they’re added.
Arguments
targetPath (String) : Where in the model this component should be added. This path is relative to the model for current component, not the root model. It can be multiple levels deep using .
.
rawModel (Object) : The model for the component dynamically being added. At a minimum this should include a sling:resourceType
, however it can be a much more complex structure consisting of multiple components. Every component found in the model is guaranteed to be processed. This synergizes well with the other new function added componentTemplate
(#21 (closed) ).
Example
Component 1: blacklight/core/components/dynamic/dynamic.js
module.exports.async = true;
module.exports.process = (model, $) => {
model.double = model.parameter * 2;
somePromise().then(()=>{
model.asyncComplete = true;
$.resolve();
});
}
Component 2: blacklight/core/components/include/include.js
module.exports.process = (model, $) => {
model.processed = true;
$.componentInclude("dynamic", {"sling:resourceType": "blacklight/core/dynamic", parameter: 5});
}
Component 2 is dynamically including Component 1 which in turn does some asynchronous work, then sets a property called asyncComplete
.
Assume we have the following raw Sling model:
{
"sling:resourceType": "blacklight/core/include",
"someKey" : "someValue"
}
The resultant processed model will be:
{
"someKey" : "someValue",
"processed" : true,
"dynamic" : {
"parameter" : 5,
"double" : 2,
"asyncComplete" : true
}
}
The dynamically added component will render just like any other component would as well.