Tuesday, January 16, 2018

Disable or Hide a Radio Button Instance

I ran across a few blogs and forum posts from people either asking or sharing how to hide or disable radio buttons. The answers I saw appeared to address only part of the story so I thought I would share a solution. PeopleCode includes functions, properties, and methods for disabling and hiding fields. As you would imagine, A field property such as Visible will show or hide a field. What makes a radio button challenging is that a radio button represents several values of the same field. The Visible property applied to a radio button's field would hide the entire radio set, not just a single radio button. Likewise, disabling a radio button's field would disable the entire radio set. What we require is a reference to one instance of a fieldset, not the base field itself.

PeopleCode includes two functions that return a reference to a field: GetField and GetPageField. The first, GetField, returns the same field reference as a standard Record.Field reference or Rowset.GetRecord.GetField. The GetPageField function, on the other hand, returns a pointer to a single instance. While this might seem like the answer, it is only part of the story. The GetPageField function does return a single instance and setting some of the properties of this single instance only manipulates the single instance. Other methods and properties, however, appear to be tied to the base field. Unfortunately, the Visible and DisplayOnly properties are two properties bound to the underlying field. Changing either of these on a GetPageField reference will hide or disable the entire radio set, not just a single instance.

The solutions I have seen, and the one I recommend, is to use CSS and/or JavaScript to hide or disable a radio button. Here is an example in Fluid:

   Local Field &compBtn = GetPageField(Page.HR_DIRTEAM_FLU, "COMPENSATION_BTN");

   rem ** hide a radio button instance;

   rem ** or disable a radio button instance;

From a visual perspective, you are done. You have successfully completed your mission. Unfortunately, however, this is only part of the answer. An important part, but only part. Hidden or disabled HTML still exists. That means I can use a standard browser tool, such as Chrome inspector or IE Developer Tools to show or enable this HTML. In fact, even if the HTML elements didn't exist, I could still invoke JavaScript to make the app server think I had selected the radio button.

The only way to ensure the server never receives the value identified by the hidden or disabled radio button is to either use FieldEdit PeopleCode or Event Mapping FieldChange Pre Processing to change the value before delivered PeopleCode ever sees that value. This is part two. This is the part that seems to be missing from other solutions I have seen.

What got me thinking about this? The Fluid My Team page contains a button bar that allows a manager to switch between alternate views. One of the radio buttons in the button bar is Compensation. Some organizations do not want managers to see compensation. My challenge was to remove the compensation radio button in a secure manner without customizing delivered definitions. Using Event Mapping on PageActivate I was able to hide the Compensation button. Event Mapping FieldChange PeopleCode ensures PeopleSoft never triggers FieldChange for the compensation button.


Unknown said...

Thanks Jim, this is exactly what i was looking for.

I have 2 radio button instances - I have set the Page Field name as ADHOC for one and BATCH for other.

I have written the below code in the page Activate. I'm not getting any error but it is not doing anything either (not disabling\hiding the radio button instance)

Local Field &ExtractByRule = GetPageField(%Page, "BATCH");
If Left(%UserId, 3) = "OPS" Then

I'm trying this on PT 8.56, PS 9.2 (PUM 27). Any idea what i'm missing here.

Unknown said...

Thanks Jim - this is exactly what i was looking for.

I have 2 radio buttons - I have set the page field name as ADHOC for one and BATCH for another

I've tried the below code as you suggested. I'm not getting any error but it is not doing anything either (not hiding or disabling the field)

Local Field &ExtractByRule = GetPageField(%Page, "BATCH");
If Left(%UserId, 3) = "OPS" Then

I'm trying this on PT 8.56, PS 9.2, PUM 27. Any idea what i'm missing here?


Jim Marion said...

@Sudhir, when you right-click and inspect the radio button after the PeopleCode runs, do you see the psc_disabled class in the button's HTML? If so, then take a look at the CSS attributes to make sure the selector is found and applied.

Unknown said...

How can one switch the radio button in front of the label instead of behind it ? In classic it is a matter of changing the properties... but in fluid it doesn't work that way.? 8.55

Unknown said...

Thanks Jim, I have a date field to hide, which I am able to using the code you provided here. Dynamically also want to unhide based on drop down value... is there a style class to unhide the field that has been hidden using style.

Jim Marion said...

Rather than apply a new style class to unhide what is hidden, the appropriate method would be to remove the style class that hid the content. Take a look at the ReplaceFFClass method in PeopleBooks, which shows an example of removing a style class.

Unknown said...

I'm using Event Mapping and a App Package to adjust the behavior of some Class Scheduling related components. For sections of a class that have 1+ enrollment we want to prevent adjusting some of the setup items (including meeting patterns). Meeting patterns are in a grid (level 2) and I can disable individual fields but I also want to prevent deleting or inserting new rows as well.

I want to use the InsertEnabled=False... but I always get this error:
"Object type Rowset property cannot be changed. (2,46) ^ PMSA"

DeleteEnabled=False DOES work fine and hides the [-] control. But I can't get the [+] control to hide. Any ideas?

&rsLvl1 = GetLevel0()(1).GetRowset(Scroll.CLASS_TBL);

For &j = 1 To &rsLvl1.ActiveRowCount;
If &ENRL_TOT > 0 Then
&rsLvl1(&j).GetRecord(Record.CLASS_TBL).GetField(Field.INSTRUCTION_MODE).Enabled = False;
&rsLvl2 = &rsLvl1(&j).GetRowset(Scroll.CLASS_MTG_PAT);
For &i = 1 To &rsLvl2.ActiveRowCount
&rsLvl2.GetRow(&i).DeleteEnabled = False;
&rsLvl2.GetRow(&i).InsertEnabled = False; /* This triggers error */
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.MON).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.TUES).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.WED).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.THURS).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.FRI).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.SAT).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.SUN).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.START_DT).Enabled = False;
&rsLvl2(&i).GetRecord(Record.CLASS_MTG_PAT).GetField(Field.END_DT).Enabled = False;

Thank in advance for any tips.
Joseph Hackbarth

Jim Marion said...

@Joseph, it used to work, as noted in this forum post: https://community.spiceworks.com/topic/2428461-how-to-disabled-row-insert-in-a-grid. Based on PeopleBooks, it seems like it is supposed to still work.

Confirm that the "No Row Insert" checkbox is NOT checked on the page at design time. That should be the only setting that would alter the behavior of the InsertEnabled property.

You may need to log a MOS ticket against this property as it used to work and is documented to work.