Wakanda/WAF — pull request #2 by quantussoftware (2013-07-15 10:15:49+00:00)
Title: Patch 1

Loading components with global datasources causes unnecessary server requests
A few weeks ago I wondered why every time I loaded a component much data is requested from the server and content of widgets is flickering. Today I discovered the cause and found also a solution.

A little background: mainly when a component is loaded all the tags in the components html file are parsed and all the datasources and widgets are created. That's fine up here. The problem is, when the widgets with data-bindings are created there is also maintained a list of the datasources which have to resolved and dispatch events to their listeners. This way all the newly created widgets get their values.
That works with local datasources but not very well with global datasources. There is some weird code in walib/WAF/Tags/tags.js, wich causes to change the current element of the datasource to force a currentElementChange event:
Code:
if (position >= 0) {
if (source.select) {
// we need this first select to "force" the select execution
if (position > 0) {
source.select(0);
source.select(position);
} else {
source.select(1);
source.select(position);
}
}
} else {
source.resolveSource();
}
As we can see, the current element of a global datasource is switched forth and back which results in lots of server requests getting the entities and all of their relation attributes.

I would expect that a global datasource with a selected element would not change when loading the component. In my opinion that's the main reason to set it global, so we can manage the context in the parent page and reuse it in various components.

I then thought about a workaround. I replaced some code in tags.js:
Code:
if (position >= 0) {
//-----begin custom-------------
//by Patrick 2013-04-12
// if (source.select) {
// // we need this first select to "force" the select execution
// if (position > 0) {
// source.select(0);
// source.select(position);
// } else {
// source.select(1);
// source.select(position);
// }
// }
//don't change element for sources which are already there
//instead dispatch an event
//use ID attribute of options object to restrict dispatch to the components widgets
if(source.dispatch){
source.dispatch("onCurrentElementChange", {ID: id});
}
//-----end custom-------------

} else {
source.resolveSource();
}
dispatch() is called in walib/WAF/DataSource/Data-Source.js. Here is the code to handle dispatching the components widgets only:
Code:
WAF.DataSource.dispatch = function(eventKind, options){
options = options || {};
var dispatchSubID = options.subID;
var dispatcherInitiator = options.dispatcherID;
var dispatcherTarget = options.dispatcherTargetID || null;
var attName = options.attributeName;
var checkAttName = false;
var match;

//-----begin custom-------------
//by Patrick 2013-04-12
var dispatchID = options.ID || null;
//-----end custom-------------

.........

//-----begin custom-------------
//by Patrick 2013-04-12
//handle restriction to component widgets
if (dispatchID != null) {
if (dispatchID) {
var regex = new RegExp("^" + dispatchID);
var listener_id = listener.id || ""; //listener.id is the widget id
match = listener_id.match(regex);

if (match && match.length >= 1 && match[0]) {
okDispatch = true;
}
else {
okDispatch = false;
}
}
}
//-----end custom-------------

}
if (okDispatch) {
var dispatchEvent = {
...........
This way only the widgets of the component are called. There are no more unnecessary server requests.