In Report Studio, Cognos provides two types of prompt validation: required and numbers-only. The validation options are available in the prompt property page:
Required validation checks to see that the prompt in question is not empty. Numbers-only validation checks to see if the contents of the prompt contains only numbers. If either configured validation check fails the associated prompt will be underlined with an orange dashed line and any ‘Next’ and ‘Finish’ buttons will be grayed out, preventing the submission of the prompt page.
This works well enough but what if you want to perform multi-prompt validation? For instance, what if you have two text prompts that have some sort of relationship and you want to validate them as a group, requiring one or more prompts, but not necessarily both to be filled out before the user continues? Consider this common real-world example:
In this example we want the user to enter in a city or a zip code value. Since the city can be easily derived from the zip code value, we want to give the user flexibility to either provide the city directly or zip code.
If we enable the ‘required’ validation for both prompts then the user will have to supply values for both before continuing:
Even though we have satisfied the city prompt, the required validation on the zip prompt will prevent the user from continuing.
By utilizing the Cognos BI JavaScipt Prompt API, we can override the default validation behavior and specify sophisticated logic that precisely matches our desired behavior. In the example provided we will allow the user to continue if either prompt contains a value.
The Technique
We will be specifying our own JavaScript function to serve as the validation function for both of the prompts. When the user types in either prompt the function will fire, determine if either prompt contains a value, and if so set both prompts to a valid state.
Preparation
Before we can reference any Cognos prompt within JavaScript we have to provide a name for the prompt in the prompt object’s Name property. Ideally, the name should conform to JavaScript variable naming conventions. See the JavaScript Identifiers section of the w3schools.com JavaScript Variables Web page for more information. JavaScript compliant names allow us to use the same name to create reference variables in the code. This makes writing and maintaining the code much easier.
Assumptions
The specified code assumes there are two text prompts on a prompt page, one with the name ‘city’ and the other with the name ‘zip’.
The Code
All code below should reside in an HTML item that is located after all prompts on the page. The code should be inserted between opening and closing script tags. See w3schools.com HTML Script Tag Web page for more information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var report = cognos.Report.getReport('_THIS_'); var city = report.prompt.getControlByName('city'); var zip = report.prompt.getControlByName('zip'); var prompts = [city,zip]; for (var i=0;i < prompts.length;i++) { prompts[i].setValidator(validate); } function validate() { var result = false; for (var i=0;i < prompts.length;i++) { if (prompts[i].getValues().length > 0) { result = true; } if (prompts[i] != this) { prompts[i].checkData(); } } return result; } |
Lets examine some interesting bits of the code:
2 3 |
var city = report.prompt.getControlByName('city'); var zip = report.prompt.getControlByName('zip'); |
We have to create a variable pointing to the Cognos API object for each prompt we want to manipulate using the getControlByName() API method. Each additional prompt added will have to have its own variable declaration.
4 |
var prompts = [city,zip]; |
We add each prompt variable to an array. This pattern is used to make it extremely easy to expand this technique to additional prompts. Additional prompts only need to have their variables added to this array. The rest of the code adapts based on the array contents.
6 7 8 |
for (var i=0;i < prompts.length;i++) { prompts[i].setValidator(validate); } |
We loop through the array assigning the validation function using the setValidator() API method.
10 |
function validate() { |
We define the custom validation function, called in this case simply: validate. This function will either return a boolean true or false value. If true is returned, Cognos treats the prompt as valid. If false is returned Cognos considers the prompt invalid, the orange line will appear underneath it, and the Next or Finish button will be disabled.
11 |
var result = false; |
We set a variable to the default validation status we want to enforce. In this example, we want all prompts to be considered invalid until we, through logic, determine that they are valid. Thus we set the variable initially to false. If we were enforcing an optional validation pattern we’d likely want to set the default state to valid and the variable to true.
12 |
for (var i=0;i < prompts.length;i++) { |
We loop through the prompts again.
13 14 15 |
if (prompts[i].getValues().length > 0) { result = true; } |
We use the API method getValues() to return the prompt values as an array. If the length of the returned array is greater than zero we know that the prompt has value and set the result to true if so.
16 17 18 |
if (prompts[i] != this) { prompts[i].checkData(); } |
We check to see if the current item from the prompts array is not the prompt whose validation function was fired. If so we execute the API checkData() method on that prompt. This is done so that all prompts are evaluated as a group. If a value is changed in one of the prompts all of the prompts are reevaluated.
20 |
return result; |
Lastly we return the result to Cognos for the prompt that initiated the validation. If none of the prompts contain data, then false is returned and the prompt is considered invalid. If any one of the defined prompts have data then the result will be true and the prompt will be treated as valid.
Conclusion
Cognos standard prompt validation works on individual prompts but doesn’t supply any way to validate a group of prompts together. By use of JavaScript and the Cognos JavaScript Prompt API, you can override this default behavior and provide group validation logic.
I would say your solution is simple and elegant but you also have to considering upgrading and maintaining the report; often with Cog upgrades JS pieces stop working and require rewriting. You could achieve the same by using an optional prompt page (with a Back button only) to display a message if values were found not to be valid. That way, you’ll use native Cognos components only with no messy JS to worry about.
Your solution would work but would result in a pretty poor user experience, in my opinion.
The solution I documented only uses calls to the Cognos provided, documented and supported JavaScript API. This API was released with Cognos BI version 10.2. It should not break with version upgrades.