Users who are familiar with Dynamics and Power Platform Model Driven Apps expect a double-click action on grids and grid-like components. By default Power Apps portals does not provide a double-click action for entity lists that are rendered on a page, and as far as I am aware, there is no configuration option to enable this.
Configure an Entity List
Here is how I achieve a double click on an entity list:
First decide on what action you want to happen when a user double-clicks. For my "Active" entity list, I want to open an advanced form to "edit" the record. So on my entity list record I configure the "edit action":
Then add some custom JavaScript to the entity list:
$(".entity-grid.entitylist").on("loaded", function ()
{
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
const href = $(anchor[0]).attr("href");
if (href == null) return;
window.location.href = href;
}
const rows = $(".entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
});
JavaScript Breakdown
The Goal
Attach a dblclick
event to each entity list row <tr>
Step 1 - Determine when the entity list has loaded
If we try to attach the dblclick
events after the document has loaded using $(document).ready()
we encounter a problem, where the entity list rows have not yet finished loading. When quering for table rows <tr>
we get an empty array.
The solution, find the entity list container and bind a function to the loaded
event of the container:
$(".entity-grid.entitylist").on("loaded", function ()
{
// Do something when the entity list has loaded
});
Step 2 - Find and bind the entity list rows
Next we need to find the table rows <tr>
for the entity list. There are multiple selectors and approaches to do this:
// 1. Direct selector
const rows = $$(".entity-grid.entitylist .view-grid table tbody tr");
// 2. Navigate children
const rows = $(event.currentTarget).find(".view-grid table tbody tr");
// 2. Navigate children, less specific
const rows = $(event.currentTarget).find("tbody tr");
Once we decide on our row retrival method we need to iterate the rows and bing the dblclick
event to each row. For readability I will define a callback function named onDblClickRow
:
const rows = $(".entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
This is added to our loaded
callback:
$(".entity-grid.entitylist").on("loaded", function ()
{
const rows = $(".entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
});
Step 3 - Implement the onDblClickRow
callback
Now we need to define an action to trigger when the row is double clicked. In my case I want to edit the record. We previously configured the edit action on the entity record, which should now be showing for each row in the action menu:
In essence, we want to click the edit button when a user double-clicks the row. We can achieve this by navigating down the DOM
, starting from the <tr>
that triggered the onDblClickRow
event.
The jQuery function on()
that we used in step 1 $(this).on("dblclick", onDblClickRow)
takes a callback as the second paramenter. Lets define the callback function, called onDblClickRow
:
const onDblClickRow = function (event) {
// Do something when the row is double-clicked
}
The callback function is passed an event
object as a parameter. We use this to get a reference to the <tr>
that tirggered the event using target.currentTarget
or this
(but I prefer to avoid this
where possible):
const onDblClickRow = function (event) {
$(event.currentTarget)
}
The we apply the find()
function to our <tr>
to search for the "Edit" button. The "Edit" button is implemented as an <a>
tag. We have only configured a single action, so only expect to find one tag, so will validate the result:
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
}
Finally we need to get the URL of the edit form for this particular record, so we fetch the href
attribute from the <a>
tag and redirect the user to that URL:
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
const href = $(anchor[0]).attr("href");
if (href == null) return;
window.location.href = href;
}
Solution
We add the onDblClickRow
callback function to our loaded
event callback and get the final result:
$(".entity-grid.entitylist").on("loaded", function ()
{
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
const href = $(anchor[0]).attr("href");
if (href == null) return;
window.location.href = href;
}
const rows = $(".entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
});
Tip
If you have mutliple entity lists on a single page you may have to modify the selector specificity and page HTML:
$("#my-active-records-container.entity-grid.entitylist").on("loaded", function ()
{
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
const href = $(anchor[0]).attr("href");
if (href == null) return;
window.location.href = href;
}
const rows = $("#my-active-records-container.entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
});
If you have multiple actions you may need to modify which <a>
tag you select, rather than index [0]
:
$(".entity-grid.entitylist").on("loaded", function ()
{
const onDblClickRow = function (event) {
const anchor = $(event.currentTarget).find("a");
if (anchor.length !== 1) return;
const href = $(anchor[0]).attr("href");
if (href == null) return;
window.location.href = href;
}
const rows = $(".entity-grid.entitylist .view-grid table tbody tr");
rows.each(function () { $(this).on("dblclick", onDblClickRow) });
});
You can even define a custom action / dialog / event by replacing the contents of onDblClickRow
.