Haven’t you ever wondered why the “Activate” button is still visible after you have selected an (already) active record?
Well, I certainty did. For me, this is a clear example of bad user experience. Having both buttons available makes no sense and it can only bring confusion. In this case it would be better to either show the “Activate” or the “Deactivate” button depending on the status of the selected record. But can we accomplish this kind behavior in Dynamics 365 Customer Engagement? In a supported way? Sure, in this blog post I will show you how.
Conditionally showing a button on a form based on a form value is pretty simple and can be accomplished by using EnableRules and DisplayRules. If you would open a contact record, you would only see the “Activate” or “Deactivate” button depending on the status of the record that is being viewed. Having the same behavior for the selected record on the HomePageGrid or Subgrid on the other hand is a bit more complex and we’ll need a little bit of JavaScript (supported JavaScript, of course).
Tip: Without having you to alter the RibbonDiffXml structure directly (which is very error prone), you can use the excellent tool from Scott Durrow, the Ribbon Workbench.
Conditionally show button based on selected record
JavaScript
Let’s start by creating our custom JavaScript. Create a new JS Web Resource named “contact.commands.enableRules.js”.
Insert the following code:
var Dynamict_Contact; (function (Dynamict_Contact) { /** * All commands from the ribbon */ var Commands; (function (Commands) { /** * Custom Enablerules (RibbonDiffXml) */ var EnableRules; (function (EnableRules) { var selectedCustomerIsActive; var previousSelectedItemId; function isSelectedContactActive(selectedEntityTypeName, firstSelectedItemId, primaryControl) { var stateCodeAttr = 'statecode'; if (firstSelectedItemId == null) return; //Selected a different item in the Grid if (previousSelectedItemId !== firstSelectedItemId) { previousSelectedItemId = firstSelectedItemId; //Retrieve the value Xrm.WebApi.retrieveRecord(selectedEntityTypeName, firstSelectedItemId.replace(/[{}]/g, ""), "?$select=" + stateCodeAttr).then(function success(result) { selectedCustomerIsActive = !result[stateCodeAttr]; primaryControl.refreshRibbon(); }, function (error) { console.log(error.message); } ); } else { return !selectedCustomerIsActive; } } EnableRules.isSelectedContactActive = isSelectedContactActive; })(EnableRules = Commands.EnableRules || (Commands.EnableRules = {})); })(Commands = Dynamict_Contact.Commands || (Dynamict_Contact.Commands = {})); })(Dynamict_Contact || (Dynamict_Contact = {}));
The JavaScript code will be triggered as soon as the Ribbon is loaded or the selected record has changed. The function should return either true (= show the button) or false (= hide the button). The code should be fairly self explanatory, so I’m not going into detail.
Ribbon Workbench
Next, we have to create a new EnableRule for the “Activate” button on the HomepageGrid by using Ribbon Workbench. Modifying buttons that came out of the box requires you to right click the button and choose “Customise Command”.
Add a new Enable Rule (1) and give it a meaningful name (ex: new.contact.EnableRule.RecordIsNotActive). Next, we add a CustomRule (3) to our Enable Rule. This CustomRule will point to our previously uploaded JavaScript.
FunctionName = Dynamict_Contact.Commands.EnableRules.isSelectedContactActive
Library = $webresource:new_contact.commands.enableRules.js
Finally, we will add three CRM Parameters (4) to our CustomRule to identify the selected record and have the correct context. To identify the selected record, we need: SelectedEntityTypeName and FirstSelectedItemId. To get the context, we need the CRM Parameter PrimaryControl.
After we finished creating our Enable Rule, we have to tie it to our command. Select the Mscrm.HomepageGrid.Active command (1), click Add Enable Rule (2) and select our new Enable Rule (3).
Finally, click “Publish” on the top of the RibbonWorkbench to save our changes:
Results
Next, we can test our result.
- Scenario A: No record selected: Both the Activate & Deactivate button are not their (OOB behavior – Enable Rule: SelectionCountAtLeastOne)
- Scenario B: A single inactive record selected: The Activate button is relevant and thus shown.
- Scenario C: A single active record selected: The Activate button is not relevant and thus not shown.
Conclusion
As you can see, with a few lines of code you can conditionally show a button based on the selected record in a grid. Implementing this functionality can greatly improve user experience. Please note that we didn’t cover the use case where multiple records were selected.
Nice
What about scenario D ?
Select 1 active and 1 inactive record.
In that case I would keep it simple and show both the “Activate” and “Deactivate” buttons. Users potentially want to bulk activate/deactivate records. For this you need to change the code and pass an additional Crm Parameter (SelectedControlSelectedItemCount).
Thank you so much for this detailed tutorial, but i think there a small problem, you need to select twice the record in order to have the best result, else if u select the record once u will may have the unsuitbale button shown.
after testing the solution deeply, i found that it works fine in UI but not in classic interfaces, So i did some resaerch, and i figure out that adding a filter on primaryControl.refreshRibbon() will solve the issue:
Solution:
Before : primaryControl.refreshRibbon();
After :
if (Xrm.Internal.isUci()){
primaryControl.refreshRibbon();
}
else
{
refreshRibbon();
}
This code is hiding the Activate button for both Active and inactive items. What could be the cause