Cardiff was the venue for UKLUG this year, two days of all yellow goodness (in every sense!). For the third time I delivered a session digging under the covers of XPages to try to give developers one or more eureka moments. At BLUG I presented on my own but couldn’t fit everything into an hour. At DanNotes I was again going solo and couldn’t fit everything into two hours. At UKLUG I presented with Tim Tripcony and we had the cunning idea of cutting the number of slides and expanding in greater detail in 20 bonus slides. We still had to cut short a couple of demos.
The slides and sample application have been sent off, so I would strongly recommend anyone in the session to look at the bonus slides, look at the bonus XPages and especially look at the statistical information as well as seeing for yourself. The sample application comes blank but loads content using the same mechanism that is in the Extension Library demo database. In the final slides of the presentation I teased about comparing languages for rendered properties – SSJS, SSJS in a DataContext, SSJS in a Script Library, Java called via Expression Language, Java called via SSJS, a VariableResolver and a server-based VariableResolver. The stats are available to compare. The demo database provided doesn’t include the server-based VariableResolver, mainly because there’s more involved to trialling that than just installing and signing the NSF. Server-based libraries like that need to be installed on the server, installed in Designer as well as being enabled for the NSF. So it’s a bit more convoluted.
Thanks again to Bill Buchan and Abigail Roberts for their cameos in the session. It taught me a lot when I was doing the investigation, things that have quite literally changed the way I code my XPages. Tim even said there were a few things he learned. Hopefully the session will get another outing, but there’s still a few eureka moments we haven’t fully covered, a few “whys” that make everything clear.
The slides are already available on slideshare http://www.slideshare.net/paulswithers1/
Here’s one that has trifled away 2 day of my life.
An onChange Javascript has this formula:
salaryCalc(“#{id:B2}”,”#{id:B3}”)
The componentID of the parameters are hardcoded here, but the CustomControl is reusable with componentID’s not necessarily B2 or B3.
There is always this kind of arrangement:
salaryCalc(“#{javascript:getClientId(‘B2’)}”,”#{javascript:getClientId(‘B3’)}”
– but here again the same problem of hard coded ID values of the two value containing components.
The componentID’s are best to be passed into Custom Properties from the containing (Parent) Custom Control.
The result is the “Long Form” name of the component i.e.
view:_id1:ap2doc:_id2:djTabContainer1:AppTab12:_id1027:EditDialog:_content:form1:EditDialog:_id2126:B2
I do not see a way to add the compositeData.hoursFieldName into the Client-Side Javascript area.
If a DataContext (e.g. “dc_hoursFieldName”) were created that evaluated the value of the var to be compositeData.hoursFieldName, the same problem of getting the DataContext variable into the Client-Side Javascript remains.
I do not see a Server-Side function that grabs the DataContext variable and returns the value of that DataContext variable dynamically naming the ID value into the Client-Side Javascript like #{javascript:getClientId(dc_hoursFieldName)} or #{javascript:getClientId(#{dc_hoursFieldName})}, which fail.
Essentially: I need a way to allow the ID of a component to be un-hardcoded value “B2” from #{id:B2} into a variable whose value is the component ID.
Putting #{id:B2} into a viewScope.put() is possible but where does the SSJS go that allows un-hardcoded compenentID name? The component name is unknown until the CC is wrapped in its containing Control or XPage.
Dynamic ID used in SSJS within CSJS
While great minds are imagining how to make the id value of a component dynamic in a SSjS string used in CSjS
e.g. “#{javascript:getClientId()}”
This is a solution that is working currently:
1.) Add a ScriptBlock to the “Parent” containing Custom Control.
2.) Code JS variables using the actual component ID’s in that CC
e.g.
var hoursFieldName = “#{javascript:getClientId(‘B2’)}”
[ScriptBlock Example]
[ScriptBlock Example]
3.) THEN, in the Javascript code behind, say “onChange” event of the Rate field on the embedded CustomControl (CC), add the ScriptBlock variable. i.e.
Old HardCoded Code:
salaryCalc(“#{id:B2}”,”#{id:B3}”)
NEW variable’ized Code:
salaryCalc(hoursFieldName,”#{id:B3}”)
[OnChangeEvent]
And for those curious about the boring JS function, here it is:
dojo.require(“dojo.number”);
function salaryCalc(hours, rate){
var hoursDojoObj = dojo.byId(hours);
var rateDojoObj = dojo.byId(rate);
hoursDojoObj.value = dojo.number.parse(hoursDojoObj.value.replace(td,””));
if (isNaN(hoursDojoObj.value))
hoursDojoObj.value = 0;
rateDojoObj.value = dojo.number.parse(rateDojoObj.value.replace(td,””));
if (isNaN(rateDojoObj.value))
rateDojoObj.value = 0;
var finalSalary = dojo.number.format((hoursDojoObj.value * rateDojoObj.value), {places:2});
return finalSalary;
}
Here’s the scriptblock & onChange event …
albeit, naked
{just add > or < to make them unashamed}:
xp:scriptBlock id=”scriptBlock1″
xp:this.value
![CDATA[var TotalFieldName = “#{javascript:getClientId(‘B2’)}”;]]
/xp:this.value
/xp:scriptBlock
xp:eventHandler event=”onchange” submit=”false”
xp:this.script
![CDATA[salaryCalc(hoursFieldName,”#{id:B3}”);]]
/xp:this.script
/xp:eventHandler