Every time Cognos refreshes or reprompts a page any custom HTML objects and the JavaScript they contain are reevaluated and run again. There are times you may want a piece of JavaScript code in a Cognos HTML object to only execute one time. For instance, you may be setting initial default values or instantiating objects and don’t want values overwritten on a page refresh or reprompt. This post will outline a simple but effective technique to ensure that the code you designate won’t execute multiple times. This ability is crucial to advanced techniques such as prompt state maintenance.
The following events will force a re-render of a Cognos page and a re-run of any custom JavaScript code you have provided:
- A reprompt action is initiated, either through a standard reprompt button, selection of a cascading prompt, or JavaScript code
- The selection of a value prompt that has its ‘Auo-Submit’ property set to ‘Yes’ and all prompts are not valid
- A drill-up or drill-down action is initiated
- A rerun of the report is executed through the toolbar run button
A Bit About Cognos Reprompts and JavaScript Persistence
When Cognos reprompts a page all of the HTML controls on the page are recreated, just like hitting F5 to refresh any other Web page. However, any JavaScript variables or objects, whether created by us or Cognos, are not destroyed and persist after the reprompt. This is how Cognos retains your current prompt values on refresh. It pulls the values from the associated JavaScript prompt objects which survive the refresh/reprompt action. Interestingly, this persistence even holds true in multi-page prompt and report pages; variables, objects or functions created on the first page of a multi-page report can still be referenced on later pages.
We can take advantage of this behavior to determine whether our code has already run once and thus should be skipped.
Code
Here is a code snippet demonstrating the technique:
1 2 3 4 |
if (typeof firstRun == 'undefined'){ // Your one-time run code goes here var firstRun = false; } |
Example
Say you wanted to set the default value of a date prompt named ‘startDate’ to a week ago today. Setting dynamic prompt defaults is a very common usage of JavaScript as Cognos gives us very limited capability to do this out of the box. You want the default value to be set when the report first runs but if the page is reprompted, you want any changes to the prompt value by the user to be retained and not have it reset back to the default value.
You take the code setting the default and put it within the if statement in the snippet above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var report = cognos.Report.getReport("_THIS_"); // Get a report instance reference. Must be done outside run-once block var startDate = report.prompt.getControlByName('startDate'); // Get a prompt instance reference. Must be done outside run-once block if (typeof firstRun == 'undefined'){ // Start of one-time run code var today = new Date(); var weekAgoToday = new Date(); weekAgoToday.setDate(today.getDate() - 7); var weekAgoTodayString = weekAgoToday.getYear() + '-' + weekAgoToday.getMonth() + '-' + weekAgoToday.getDate(); startDate.addValues([{"use":weekAgoTodayString}]); // Use Cognos API addValues() function to set the default // End of one-time run code var firstRun = false; } {Regular JavaScript code continues here} |
On first run, the code inside the if block will be executed and the prompt will be set to seven days previous to the current date. If the user changes the prompt value and then reprompts the page the code setting the default value will be skipped as the firstRun variable will exist. Thus, the user’s selection will be preserved. Any other one-time run code can be added to the if block as necessary.
Explanation
We check if the variable firstRun already exists and if not we execute the code. At the end we create the variable so that next time the page is refreshed or reprompted the typeof check will return false and the code will be skipped.
Note that we are using a global variable, in this example firstRun. This variable can be any valid JavaScript variable name you like. However, care should be taken in naming this variable. The name should be unique since it could potentially collide with other variables declared in the global space, including variables Cognos itself declares. For this reason I recommend namespacing all variable and object names in Cognos custom JavaScript. This is a simple naming scheme that adds variables, objects, and functions as properties or methods of a root object. Variables then are referenced with dot notation in relation to the root. If your root name was cjl, then the variable firstRun would be referenced as cjl.firstRun. I will cover namespacing in-depth in a future post.
With this simple bit of code you can isolate initialization code and have it run only once per report regardless of subsequent reprompt or refresh actions.
Update: 6-21-2017
After this article was published, I learned some new things about how Cognos handles object instantiation. When a page is reprompted, Cognos creates whole new object instances for all prompts and for the report itself. The old intances still exist but are effectively orphaned and no longer represent anything on the page. This means that any variable assignment to object instances has to take place on every reprompt. We want to get a reference to the newest instances of the object each time. Thus, these assignments cannot reside within the “first run only” section of the code. I have revised the sample code to reflect this.
Hi Scott,
This is very old post, hope I can reach to you by commenting here with my issue.
I have used same technique in one my Cognos 11.10 report, it is working working fine if I run report from editor but it’ is throwing error when I run the report directly fro m the portal.
That’s strange. Unfortunately, I don’t have access to Cognos 11 and thus none of the code here was tested on it. That said, I believe that Cognos 11 supports the same JavaScript Prompt API that was introduced in version 10.2.
Can you supply the error you are getting? I might be able to give you some insight.
great post!
Brilliant. exactly what I was looking for. Thank you.
Beautiful. A bit more fleshed out example would probably be helpful but thank you and keep em coming!
Dave
Thanks for the feedback Dave. Based on your suggestion I’ve added an example section to show how the technique would be used in practice.
Sweet Technique !!
I used to do it with some default values set in the hidden prompts which would later be changed by the JS code. If the hidden prompt has the default value, then it is the 1st run.
No onwards, ‘am gonna go with your technique.
Thanks
I’m glad to hear it was helpful. Thanks for the feedback.