Action Buttons - PaulNieuwelaar/alertjs GitHub Wiki
/!\ Action Buttons is in beta. Download the solution and sample data to try it out, or Contact us for more information and feedback.
Action Buttons give super users and non-developers (and also developers) an easy way to build custom buttons and logic in Dynamics 365 without having to add and configure command bar buttons manually, and without having to write any code.
Action Buttons can be run by users from the 'Actions' flyout menu added to any entity forms or views where an activated Action Button has been added.
Inspired by the old (now deprecated) 'Dialog' processes which gave users the ability to create simple or complex wizards using a 'workflow-like' editor.
Each Action Button has a set of actions that will be executed when a user clicks the button. Each action can specify conditions, allowing you to create custom validation and branching within your process.
Actions can include displaying a dialog, which you can fully customise to include fields and buttons with further actions. Dialogs can be chained together to create a wizard or branching pages. Inputs will be passed through between pages, allowing you to easily create Back/Next buttons between pages.
Or you can trigger a Power Automate Cloud Flow to perform custom logic at the end of your process, passing through any inputs and context information collected during the process.
Developers can also make use of the JavaScript Function actions to do more advanced logic, while still benefiting from the Action Buttons and Dialogs to create the user interface.
- Ensure you have the latest version of Dialog Builder installed (at least v3.1.5). For production environments, you must also purchase a license.
- Download and import the Actions Buttons - beta solution through make.powerapps.com -> Solutions. During the import you'll need to create or map connections for Common Data Service (current environment) and Power Platform for Admins.
- If you import using the classic import process, the flows will be off by default, and will need to be manually updated and turned on.
- Once installed, you'll be able to access the Action Buttons and other related entities within the Action Buttons app. It is also recommended to install the Sample Data (next section) as this includes some useful buttons and dialogs to help you build action buttons.
Download sample data The sample data includes 6 entity XML files, which can be imported individually in the order of Action Buttons, Dialogs, Dialog Actions, Dialog Conditions, Dialog Fields, Dialog Buttons. Or import the whole zip file and Dynamics 365 will sort out the dependencies/order.
3x Action Buttons are included in the sample data:
-
Quick Add Contact
Displays a dialog to quickly add a contact to the selected account by capturing the first name, last name, and email address, then triggers a cloud flow with the captured inputs.
This example shows you a simple-end to-end process using an action button, dialog, and flow, plus several other conditional actions, including validation to only be used on active accounts, and also to enforce a first or last name is entered.
- After installing the sample data, you'll need to manually update the Flow Trigger URL on the Dialog Action named: '
Trigger flow, then show success dialog
'. This should be updated to the HTTP POST URL from the example flow included in the Action Buttons solution, named: 'Account - Quick Add Contact (Action Button Example)
'. This URL is different for each environment.
- After installing the sample data, you'll need to manually update the Flow Trigger URL on the Dialog Action named: '
- Preview Dialog Previews the selected dialog, without passing through any selected records. This is just a really useful button to have while editing a Dialog, as you can quickly preview the dialog without having to navigate away from where you are, so you can quickly validate you've got your dialog looking right.
-
Create Flow from Template
Create a new Cloud Flow with an example HTTP Trigger and sample body.
Another really useful button to have. While on a Dialog Action, you can use this button to trigger the creation of a new Cloud Flow with all the default paramaters from the current dialog passed through by default. There's also a toggleable field on the form which triggers the same logic.
- Once a cloud flow has been created, you need to copy the HTTP POST URL back to the Flow Trigger URL.
These entities are all available from within the Action Buttons app, provided with the solution.
Published Action Buttons will display in the Actions menu on the specified entity, depending on the Display Area. The Actions menu will only appear on an entity form/view if there is 1 or more published action button with a matching display area.
Action Buttons have the following fields:
- Entity Name (required) - The entity schema name to display this action on. Has autocomplete to help select/enter the correct name. Must be a valid entity name.
- Display Area (required) - Specify where to display the button, and whether one or more records need to be selected. This is a multi select optionset, so each action button can be displayed in multiple different areas, e.g. form and views.
- Button Group Name - The name of the group to display the button under in the Actions flyout menu for the specified entity.
- Button Icon - Display a custom icon next to the button in the Actions menu. Web resources should be prefixed with '$webresource:' (SVG images preferred). Microsoft's Modern Images like 'Assign' can also be used. Has autocomplete to help select/enter an image web resource, however this is just a guide, and can be ignored if using a Modern Image.
- Button Name (required) - The name of the button displayed in the Actions flyout on the specified entity form. This is the primary field for the entity.
- Status Reason - Activated action buttons will be displayed on the associated entity. Draft will be removed. Set to Activated by default when creating a new action button.
- Description - Provide a description about what this action button does. This description does NOT display to users when using the action buttons, and is only for information purposes when editing action buttons.
- Owner - You can control access to action buttons by assigning ownership to a specific user or team, or sharing the action button with users or teams.
Each Action Button should have at least 1x Action associated. Actions associated to an Action Button allow you to perform pre-validation before displaying a dialog, or directly call a flow without prompting for any inputs or confirmation first. This can also be useful when triggering custom JavaScript functions.
[Placeholder]
[Placeholder]
[Placeholder]
Dialog Actions are associated to either a Dialog Button, or an Action Button. Each Action Button or Dialog Button can have multiple Dialog Actions associated to it. In these instances, the first Dialog Action whose conditions are met will be executed (starting from the lowest Order).
This allows you to perform validation before triggering the next step in a process, or to create branching based on previous inputs.
Dialog Actions have the following fields:
- Order - The order of execution where multiple actions exist for the same button. The first action meeting the conditions will be exeucted. Lowest are validated first.
- Name (required) - A friendly name to help identify what this action does.
- Rule Logic - Specifies how the associated conditions are evaluated. AND = All conditions must be true. OR = 1 or more conditions must be true.
- Flow Trigger URL - The URL of an HTTP request triggered Flow. Response data from the Dialog is sent to the flow when this button is clicked, and the conditions are met.
- Child Flow - Select a child dialog to run when this button is clicked, and the conditions are met. Used to perform paging, branching, or custom validation.
- Create Flow from Template - Used to trigger the creation of a new templated flow.
- Flow Editor URL - Used for editing purposes only. Automatically set when using 'Create Flow from Template'. The Flow URL for the HTTP trigger must still be set manually.
- JavaScript Web Resource - The name of a web resource to load. This is only required if the web resource isn't already loaded onto the form. If set without a JavaScript Function, the next action is also triggered. Autocompletes to help select the correct name.
- JavaScript Function - Executes a custom JavaScript function with the response object from the action/dialog, and the formContext. The JavaScript Web Resource field should also be set if not already loaded on the form.
Each Dialog Action can have 1 or more of the following actions:
The HTTP POST URL obtained from a Power Automate Flow trigger step 'When a HTTP request is received'.
Use this at the end of your process to capture all the inputs and data collected from the action button or dialog(s), and pass it through to the flow for further processing. Use the 'Create Flow from Template' toggle field on the form to automatically generate a new flow, using all the inputs from the dialog (if applicable).
The following properties are always passed through to the flow, in addition to any custom Dialog Fields:
- _entityType (string) - The entity schema name the action button was initiated from.
- _entityIds (Array of strings) - The ID of selected records the action button was run for. This can be empty, depending on the Display Areas for the Action Button.
- _entityId (string or null) - The ID of the selected record, if exactly 1 record was selected. Useful for simple action buttons where you know only a single record will be selected, so you don't need to apply-for-each.
- _userId (string) - The ID of the user who triggered the action button.
- _parentType (string or null) - The entity schema name of the parent entity, when the action button is used from a subgrid.
- _parentId (string or null) - The ID of the parent entity, when the action button is used from a subgrid.
Note: If you provide a Response step at the end of your flow, the system will wait for the flow to complete. Otherwise if there is no Response step, the flow will fire off in the background.
A lookup to a Dialog record. Use this to display a dialog as the next step in the process. Can be used to create multiple pages within a process, or branching down different paths. Responses from previous dialogs can be passed between pages, so all data can be collected and sent to a flow at the end of the process.
If used with a Flow URL in the same action, the dialog will only be displayed after the flow response has been received. You can use the dynamic placeholder value {{flow.response}} in your child dialog to use the custom flow response. This is useful when displaying a success dialog where a flow is returning some important information to display back to the user.
Use this, along with the JavaScript Web Resource field, to specify a custom JavaScript function to be executed when the button is selected. If used with the Flow URL action, it will execute after the flow response is received, and will include the flow response in the responseObj. The function accepts up to 3 paramaters:
- formContext (Object) - The formContext obtained from the form or view.
-
responseObj (Object) - Contains all the inputs from the process, including the
_userId
,_entityType
and_entityIds
. Any fields from dialogs will also be included as a key/value pair, where the key is the Dialog Field ID, and the value is the value entered by the user (the data type will depend on the type of field used). - flowResponse (String) - If used with the Flow URL action, this will contain the response text from the flow.
[Placeholder]
{{placeholder}}
2x Security Roles are included in the solution:
- Action Button Editor - Users with this role have access to create action buttons, dialogs, and all associated config record types for themselves. Users can only create and edit records they own, or have shared access to. These users also have access to the Action Buttons app, where they can access the config records.
- Action Button User - Users with this role have access to use action buttons and dialogs, but cannot create or modify the config records. Users will need this role in order to see and use the Actions menu.
These functions are used internally when an action button or dialog button is clicked, and are made available externally as well for developers to call these steps manually. These can be used in the 'JavaScript Function' callback from an action button or dialog. These can also be used anywhere else in your solution by adding a reference to mag_/js/actions.ribbon.js
. A reference will also need to be added for mag_/js/alert.js
if an action button wasn't clicked prior, and your action button has a child dialog action. Both of these libraries are automatically loaded when an action button is clicked from the Actions flyout menu.
Use this function to manually trigger an action button from custom code. The action button triggered does not have to be activated, allowing you to hide the action button from the default 'Actions' flyout menu.
Actions.triggerActionButton(actionButtonId, responseObj, formContext)
actionButtonId
- Type: String. The GUID of the Action Button record to trigger. This should be obtained dynamically unless the Action Button GUID's are maintained between environments (recommended).
"15b1c1b4-767a-eb11-a812-000d3ac89545"
responseObj
-
Type: Object. (Optional) The object passed between dialogs, and sent to the Cloud Flow at the end of the process. Contains all the inputs from the process, including the
_userId
,_entityType
and_entityIds
(if provided). Can also be used to pass through default values for dialog fields, or to pass through additional values to the flow at the end of the process. If_entityType
is set, and_entityIds
contains exactly one ID, the record will be retrieved to be used with dialog dynamic values.
{
_entityType: "account", // Selected entity
_entityIds: ["05bb87a6-e2fe-462c-aa8b-0a11757e9eec"], // Selected record(s)
_userId: Xrm.Utility.getGlobalContext().userSettings.userId, // Current user
firstName: "Paul", // Default value on dialog
extraMetadata: 123456 // Extra value to send to flow
}
formContext
- Type: Object. (Optional) The formContext obtained from the form or view. Used to automatically refresh the form/view after a cloud flow has been triggered.
executionContext.getFormContext()
The following code sample triggers the 'Update Account Details' action button for the opened account record (i.e. from the form).
var formContext = executionContext.getFormContext();
var actionButtonId = "15b1c1b4-767a-eb11-a812-000d3ac89545"; // Update Account Details
var entityName = "account";
var entityId = formContext.data.entity.getId(); // Current record
var userId = Xrm.Utility.getGlobalContext().userSettings.userId; // Current user
var responseObj = {
_entityType: entityName,
_entityIds: [entityId],
_userId: userId
};
Actions.triggerActionButton(actionButtonId, responseObj, formContext);
Use this function to manually trigger a dialog from custom code. This can be used independenly from an action button, allowing you to call directly into a dialog from anywhere.
Actions.triggerDialog(dialogId, entityObj, responseObj, formContext)
dialogId
- Type: String. The GUID of the Dialog record to trigger. This should be obtained dynamically unless the Dialog GUID's are maintained between environments (recommended).
"3bc21c4b-5c76-eb11-a812-000d3ac8b885"
entityObj
-
Type: Object. (Optional) The WebApi result for the selected record. This is used when dialog fields have default values from the record using
{{fieldname}}
. The object structure typically has the field schema name as the key, and the field value as the value. Lookups use_fieldname_value
etc.
{
accountid: "05bb87a6-e2fe-462c-aa8b-0a11757e9eec",
name: "Frosty's",
telephone1: "555-1234"
}
responseObj
-
Type: Object. (Optional) The object passed between dialogs, and sent to the Cloud Flow at the end of the process. Contains all the inputs from the process, including the
_userId
,_entityType
and_entityIds
(if provided). Can also be used to pass through default values for dialog fields, or to pass through additional values to the flow at the end of the process.
{
_entityType: "account", // Selected entity
_entityIds: ["05bb87a6-e2fe-462c-aa8b-0a11757e9eec"], // Selected record(s)
_userId: Xrm.Utility.getGlobalContext().userSettings.userId, // Current user
firstName: "Paul", // Default value on dialog
extraMetadata: 123456 // Extra value to send to flow
}
formContext
- Type: Object. (Optional) The formContext obtained from the form or view. Used to automatically refresh the form/view after a cloud flow has been triggered.
executionContext.getFormContext()
The following code sample triggers the 'Quick Add Contact' dialog for the opened account record (i.e. from the form), and sets the default value of the firstName
dialog field to 'Paul'.
var formContext = executionContext.getFormContext();
var dialogId= "3bc21c4b-5c76-eb11-a812-000d3ac8b885"; // Quick Add Contact
var entityName = "account";
var entityId = formContext.data.entity.getId(); // Current record
var userId = Xrm.Utility.getGlobalContext().userSettings.userId; // Current user
var entityObj = await Xrm.WebApi.retrieveRecord(entityName, entityId);
var responseObj = {
_entityType: entityName,
_entityIds: [entityId],
_userId: userId,
firstName: "Paul"
};
Actions.triggerDialog(dialogId, entityObj, responseObj, formContext);
Use this function to manually trigger a Power Automate HTTP Flow from custom code. This can be used independenly from an action button, allowing you to call directly into a flow from anywhere, and get the response.
Actions.triggerHttpFlow(flowUrl, responseObj, formContext, successCallback, errorCallback)
flowUrl
-
Type: String. The HTTP POST URL obtained from a Power Automate Flow trigger step 'When a HTTP request is received'.
"https://prod-13.australiasoutheast.logic.azure.com:443/workflows/xxxx/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=xxxx"
responseObj
- Type: Object. (Optional) The object sent to the Cloud Flow. This object is posted to the flowUrl as JSON. Typically contains the values from the action button/dialog, but can be used to send any values to the flow.
{
_entityType: "account", // Selected entity
_entityIds: ["05bb87a6-e2fe-462c-aa8b-0a11757e9eec"], // Selected record(s)
_userId: Xrm.Utility.getGlobalContext().userSettings.userId, // Current user
firstName: "Paul", // Default value on dialog
extraMetadata: 123456 // Extra value to send to flow
}
formContext
- Type: Object. (Optional) The formContext obtained from the form or view. Used to automatically refresh the form/view after the cloud flow has been triggered.
executionContext.getFormContext()
successCallback
-
Type: Function. (Optional) The function to call after the flow has been triggered. If the flow has an HTTP Reponse step, this will be once the flow has completed successfully, and will contain the
response
from the flow. If there is no HTTP Response step, the success callback will run immediately after the flow is triggered, regardless of whether it completes successfully.
function (response) {
// Do something with the flow response
console.log(response);
}
errorCallback
-
Type: Function. (Optional) The function to call if the flow encounters an error. Contains the
error
message returned from flow, as well as the fullresponse
. If there is no HTTP Response step in the flow, the error callback will not run, as the success callback will fire before the flow finishes running.
function (error, response) {
// Do something with the error
console.error(response);
alert(error);
}
The following code sample triggers the 'Quick Add Contact' flow for the opened account record (i.e. from the form), and passes through values for firstName
, lastName
, and email
.
var formContext = executionContext.getFormContext();
var flowUrl = "https://prod-13.australiasoutheast.logic.azure.com:443/workflows/xxxx/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=xxxx"; // Quick Add Contact
var entityName = "account";
var entityId = formContext.data.entity.getId(); // Current record
var userId = Xrm.Utility.getGlobalContext().userSettings.userId; // Current user
var responseObj = {
_entityType: entityName,
_entityIds: [entityId],
_userId: userId,
firstName: "Frosty",
lastName: "Stevens",
email: "[email protected]"
};
Actions.triggerHttpFlow(flowUrl, responseObj, formContext, function (response) {
// Success
console.log(response);
}, function (error, response) {
// Error
console.error(response);
alert(error);
});