Until now I only knew a rather bad way of doing this, which would be to write code in the report query like:
select case when program_status='VALID'
then '<a href="f?p=MYAPP:123:&SESSION.::&DEBUG.:123:P123_PROGRAM_NAME:'
|| program_name || '">' || program_name || '</a>'
else program_name
end as program_name,
Not only is it ugly and hard to write, it has some other issues too:
- I need to change the column's "Display As" from the default to "Standard Report Column" to prevent the link HTML being escaped and displayed literally. And this may be frowned upon as a potential security risk.
- If using session state protection (SSP) then I need to add a checksum to the URL by calling apex_utils.prepare_url. Now I have a function call in the SELECT clause, which may cause performance issues.
I now have a different solution, based partly on Tyler Muth's Conditional Column Formatting post.
Here is the query for my report above:
select program_name
, program_status
, case when program_status != 'VALID' then 'nolink' end as class_name
from spl_programs
The third column CLASS_NAME will be set to 'nolink' on all rows that do not have the 'VALID' status. This column is then set to not show in the report.
In the column attributes for the PROGRAM_NAME column, I define the column link in the usual manner, except that I add class="#CLASS_NAME#" in the Link Attributes:
I can add some CSS to make "nolink" links look like plain text, and also not have the cursor change when hovering over the link:
a.nolink {
color: #000;
cursor: default;
}
But the user could still click on the link. To prevent it redirecting to the other page I can change the onclick event for all "nolink" links with some "Execute when page loads" Javascript:
$('a.nolink').attr("onclick","return false;");
Now if the user clicks on the link, nothing happens. But in theory they could disable Javascript and reinstate the default link action. Or they could view the page source or use Inspect Element to see the link's URL, and copy/paste it into the browser. In some cases that may not matter, but if it does matter then it should be prevented, for example by adding an appropriate Authorization Scheme to the target page.
One possible issue (a colleague just reminded me) is accessibility - although it no longer looks like a link, and does nothing when clicked, to a screen reader program it is still a link, and the screen reader user may be mystified as to why it doesn't work. Perhaps instead of "return false;" it should have"alert('You cannot open this program as it is invalid');". Or there may be a better solution?