We implemented a custom data source control that retrieves messages from a web service. The data source has a number of properties, some of which are bound to other SPEAK controls for example:
- Sorting – Bound to List Control
- Search Text – Bound to Text box
- Message Type – Drop down
Therefore we need to wait until all the bound properties are set before we call the web service to avoid unnecessary web service calls.
In the model we detect when the last property is bound (i.e. its value changes from empty to some value). In this case we used the MessageType when it contained a value it was assumed it was OK to call the web service.
This worked until the server side control code was re-factored and the following code was called first in the constructor and not last:
The “Get String” function is responsible for generating the data-sc-bindings attribute of the control, which defines the bindings and the order they are bound (probably requires another post to explain all the magic that SPEAK does here).
Therefore as this was now called first, not last, each time the search text, sorting was bound another web service call was made. We could not detect if search text or sorting parameters had been bound or not as either of these properties can contain an empty string. It is not a great strategy to check all the properties and try to determine if they are bound or not and or rely on the order they are bound.
Therefore I investigated the life cycle to determine if there is an event, trigger, etc. I could use to determine when binding for a control is completed.
Control View life cycle
The life cycle for a control’s view is implemented as a pipeline (see my previous post about pipelines). The pipeline defines 5 steps:
- Initialization – call the view’s initialize function
- Applying Cross Binding – Bind all the properties for the control, and child controls that have bindings.
- Before Render – If the view declares a beforeRender function it is called.
- Render – If the view declares a render function it is called.
- After Render – If the view declares a afterRender function it is called.
A very simple solution was to add a beforeRender function to the view (see image below) and set the isReady to true and call Refresh on the Model.
As beforeRender is called after all the bindings are bound, the refresh function only needs to check if isReady is true before calling the web service. The Refresh function has to check isReady as it is called each time a property changes and or the first time it is bound.