In Power Apps Portals, the main navigation menu is represented by the Web Link Set and Web Link objects (entities). A Web Link contains a reference to a Web Page from the Portal or an external URL. The Web Link Set contains a group of Web Links, and can be placed via Liquid template in the Portal.
When setting up Power Apps Portals, by default, it comes with with a few Web Link Sets pre-defined. The Default Web Link Set is used as the primary menu in your Portal. For a better understanding of all the properties of Web Links and Web Link Sets, please refer to the following documentation: https://docs.microsoft.com/en-us/powerapps/maker/portals/configure/manage-web-links.
The way the menu is rendered by default, we cannot have sub-menus or a title to split Web Links. In this post, I will show you a quick tip on how to setup a tree structure for your Portal menu/primary navigation, something like this:
MENU – – – – – – – – – – – – TITLE 01 LINK A LINK B TITLE 02 LINK A LINK B
Implementation
To achieve this, I am going to make customizations in the Web Link entity. There is no problem modifying the OOB Portal entities, just make sure you add any changed objects to an unmanaged solution when moving to other environments, you can’t export the Portals solution as it is a managed solution.
The code that renders the menu is in Liquid Template, and it’s placed in the Header Web Template, we will also make a few changes there.
By default, if you add a custom field to your Portal entities, it will be reflected in the Liquid objects, so you can easily access the value without writing additional code.
If for some reason you prefer not to change the entity, that's fine, another approach would be when creating your Web Link record, add some tag in the name (for example *menu-title*)
Now let’s jump into the customization:
Create a new field in the Web Link entity (I am calling “Display as Title”)
Add the new field to the Web Link form
I am leaving Page / URL blank, additionally if you want you could add a business rule to hide/show those fields according to the Display as Title value
Now open your “Header” Web Template, I am changing the code with the following logic:
If my custom field “ollie_displayastitle” is true, display the link as a title instead of an <a> element
In my example, I am using a <strong> element, but you could use anything here, preferably you should also add a class from your CSS to get a better look & feel
If you didn’t create the custom field and are using the tag like I mentioned *menu-title*, your if condition will be {% if sublink.name contains “*menu-title*” %} and then you also need to remove that using liquid filter {{ sublink.name | remove: “*menu-title* “}}
This snippet of code can be found on the line 62 for the Header Web Template (OOB Portals):
{% for sublink in sublinks %}
<li role="none">
{% if sublink.ollie_displayastitle %}
<strong>{{ sublink.name | default:sublink.title | escape }}</strong>
<!-- this can be any element type -->
{% else %}
<a
role="menuitem"
aria-label="{{ sublink.name | default:sublink.title | escape }}"
href="{{ sublink.url }}"
{% if sublink.Open_In_New_Window %}
target="_blank"
{% endif %}
{% if sublink.nofollow %}
rel="nofollow"
{% endif %}
{% if sublink.tooltip %}
title="{{ sublink.tooltip | escape }}"
{% endif %}>
{{ sublink.name | default:sublink.title | escape }}
</a>
{% endif %}
</li>
{% endfor %}
This is the final result:
Conclusion
By customizing Portal entities and existing Web Templates, we are not only making customization to the Portals but also extending its original functionality.
This post idea came after seeing a few questions on the communities about changing the way the menu is rendered. I hope this post encourages you to make changes to the way the menu is rendered OOB.
I recently came across an interesting requirement that I thought would be worth sharing here. Yet again I will be working with Entity Lists, and some implementations will be used from previous posts.
Business Requirement:
Display list of records in the Portal
Allow users to download a document with record details (including child entities)
Document should be (preferably) Word format
The document should also be available in D365
Before we dive into the details, here is a sneak peek of what will be achieved by the end of this post:
To achieve this, I will use the following components:
Web File with the Word icon
Web Page and Entity List for the Contact entity
Entity List actions
View record details
Run Workflow (to generate the Word Document)
Entity Permissions
Custom entity (Application) with the following relationship:
Contact 1:N Application
Word Template against the Contact record, displaying contact details and a list of Applications
Workflow to set generate Word Template against the Contact record
CSS customizations to display my workflow actions as icons
JavaScript code to dynamically create the download button
Implementation
My overall approach for this will be using as much as possible existing D365 features, I won’t write any custom code in D365, only client-side code in the Portals will be necessary.
Web File:
As I want my Entity List to display a Word Icon, I am creating a Web File and uploading the icon from IconFinder.com
I want to use a Word icon for my “Generate Document” workflow action in my entity list, so I am adding one more class to my CSS, this is to set the height and position of my image (you wouldn’t need this if you were using icons within the bootstrap/glyphicon):
The Word document will be generated as a Note attached to my Contact record in D365, for this reason we need to have an entity permission for the Note entity, this is a child entity permission against my Contact entity permission, for more details on parent/child entity permissions please refer to the following documentation: https://docs.microsoft.com/en-us/powerapps/maker/portals/configure/assign-entity-permissions
D365 Application Entity/ Contact Entity
I have a custom entity called Application, with some very simple fields for this demo such as ID, Status, Type and Created On.
Another customization I am making is adding a custom field (Text/URL) in my OOB Contact entity to store the URL of my document, I am calling this “Generated Document URL”.
Finally make sure this URL field is available in your view being displayed on the Portal, in my case the Active Contacts view. Don’t worry, we will hide the column via JavaScript, but this will be important on a later stage.
Word Template
I am using the OOB Word Template feature to generate my document. What I like about this is that we can generate the document manually via D365 or through a workflow, which is perfect for my scenario. For more details on how to create the Word Template please refer to the following: https://docs.microsoft.com/en-us/power-platform/admin/using-word-templates-dynamics-365.
My template will display a logo image, the Contact name and e-mail and a list of the existing Applications.
Workflows
We need two sync workflows to achieve our need. Here I will describe each of the workflow steps:
Generate Word Document
Sync Workflow
Trigger: On-Demand
Entity: Contact
Scope: Organization
Steps:
- Perform Action: SetWordTemplate (pass the contact record and set the Word Template created as actions parameters)
The SetWordTemplate is an OOB action that creates a note against the record with the generated Word Document.
A note record in your Portal can be accessed via the following URL pattern: <portalurl>/_entity/annotation/<note guid>, so now we need to generate the URL against the Contact record. For this I am creating the below workflow:
Set Contact Generated Document URL
Sync Workflow
Trigger: Record is created
Entity: Note
Scope: Organization
Steps:
- Validate if the Regarding field of the note is a Contact
- Validate if the File Name is <your word template name> (you can make better validations, I am going for simple ones for this demo)
- Now we need the note GUID, to avoid code I am using the D365 Workflow Tools solution: https://github.com/demianrasko/Dynamics-365-Workflow-Tools/blob/master/docs/GetRecordID.md but you could also write your own custom code to retrieve the record GUID
- The next step is to update the related Contact record with the URL pattern + Note GUID. All we need here is the relative path, no need for the Portal root URL (as this might change between environments or other reasons)
Entity List JavaScript:
At this point we have the core of our development done. If you navigate to your Web Page you should have the Word icon to generate your document, and once triggered, the URL column from your view, once empty, should get populated with the document URL, if you click that URL you should be able to download your document.
Now we need to add a JavaScript logic, attached to the Entity List Load event, that will perform the following actions:
Hide URL column
For each row:
Get the URL from the “Generated Document URL” attribute
If this contains data, create dynamically an element in the same structure as the other elements
Append new element to the workflow links so it will be the last action
The following JavaScript code can be placed in the Entity List custom JavaScript section:
Now after refreshing the cache and your Web Page you should see the below behavior:
Caching Issues?
We all know the Portals have some caching issues, but this shouldn’t be an issue with the above implementation. For any actions triggered by the Portals, the cache is automatically refreshed for that record, as in our scenario we are using sync workflows, the cache gets refreshed within the same transaction.
Conclusion
My example was specific to generate a Word document using a Word Template in D365, but this approach could be used for several other requirements where you have a workflow updating the main record in real-time, and appending a dynamic link to anything on your entity list.
Have you ever had a similar requirement? Please comment below with how you implemented it.
If you find this post useful feel free to like and share it.
But if we have too many Actions setup in our Entity List, the page gets very busy, so it may not be ideal. In this post I am going to show another way to achieve a similar result using JavaScript/jQuery, but this time we will leave the main actions (Details/Edit/Delete) as icons, and the remaining in the dropdown.
So I am going to remove the CSS from my Web Page, and my Entity List is going back to this state:
If you didn’t see my previous post, what I have here is a simple Entity List pointing to my Active Accounts view from my CDS environment, and I have a few actions setup as part of my Entity List (Edit/View Details/Delete/Run Workflow to send an e-mail).
Now it’s time to write the JavaScript, there are tons of ways to approach this, I will describe the actions I am performing in my JavaScript:
Validate that my list contains actions associated
Create an object with the rows from the list
Start looping the list rows
Create an object with the actions for that row (only actions for Edit/Details/Delete)
Start looping the actions
Create an object to store the span class of the action, which contains the icon
Create dynamically a new <span> with the previous class and add that to the main action element
Via JS I am adding some styling, but you can also set a class from your CSS and reference it here, you can also change those properties if you prefer the icons bigger/smaller
Remove the old action element
Create an object with the actions for that row (Workflow)
Start looping the actions
Here I will replace the current <div> element for a new <a> element
Again I am manually applying some styling that could be in the CSS
Move the <a> element to the far right by appending to the previous object
Finally we can remove the old dropdown button completely
$(document).ready(function () {
ChangeGridButtons();
});
ChangeGridButtons = function () {
$(“.entity-grid”).on(“loaded”, function () {
if ($(this).find(“.view-grid .table tbody tr td:last-child ul.dropdown-menu > li > a.details-link, .view-grid .table tbody tr td:last-child ul.dropdown-menu > li > a.edit-link, .view-grid .table tbody tr td:last-child ul.dropdown-menu > li > a.deactivate-link, .view-grid .table tbody tr td:last-child ul.dropdown-menu > li > a.delete-link, .view-grid .table tbody tr td:last-child ul.dropdown-menu > li > a.disassociate-link”).length > 0) {
var rows = $(this).find(“.view-grid .table tbody tr td:last-child”);
$.each(rows, function (index, row) {
var actions = $(row).find(“ul.dropdown-menu > li > a.details-link, ul.dropdown-menu > li > a.edit-link, ul.dropdown-menu > li > a.deactivate-link, ul.dropdown-menu > li > a.delete-link, ul.dropdown-menu > li > a.disassociate-link”);
$.each(actions, function (index, action) {
var li = $(action).parent();
var iconClass = $(action).find(“span”).attr(“class”);
$(action).append(“<span class='” + iconClass + “‘></span>”);
$(action).append($(action).find(“span”));
$(action).css(“font-size”, “18px”);
$(action).css(“text-decoration”, “none”);
$(action).css(“padding-right”, “4px”);
$(row).append($(action));
li.remove();
});
var actions = $(row).find(“ul.dropdown-menu > li > a.workflow-link”);
if (actions.length > 0) {
var divDropDown = $(row).find(“div.dropdown”);
$(divDropDown).css(“display”, “unset”);
$(divDropDown).append(“<a class=’dropdown-link’></a>”);
var aDropDown = $(divDropDown).find(“a.dropdown-link”);
$(aDropDown).attr(“aria-expanded”, “false”);
$(aDropDown).attr(“data-toggle”, “dropdown”);
$(aDropDown).css(“text-decoration”, “none”);
$(aDropDown).css(“cursor”, “pointer”);
$(aDropDown).append($(divDropDown).find(“span”));
// move dropdown to the far right
$(divDropDown).appendTo(row);
}
$(row).find(“div.dropdown”).find(“button”).remove();
});
}
});
};
You can place the above code in the Entity List or Web Page custom JavaScript section, and now this is how our Entity List looks:
JavaScript VS CSS – Which one is better?
Well, there is no right or wrong, it really depends on your scenario/requirement.
Performance wise we can expect the CSS method would be better, but usually you won’t have an Entity List displaying a large number of records per page, by default an Entity List displays 10 records per page, so the JavaScript should run quick enough. It also depends on what you are most comfortable with, performing style changes or code changes.
I hope you find this post useful for your Portals project.
These Actions are displayed in a dropdown list on the right side of each record:
For a nicer UX, I will show you how to display the actions as icons within the list row.
There are a few different ways to achieve this, I will write two posts, one using CSS, and another one using JavaScript.
To start, I am creating an Entity List pointing to the Active Contacts view in my CDS environment.
Now I am creating the following actions against my Entity List and the necessary components involved:
Edit Action – Entity Form to edit the record
View Details Action – Web Page to view record details
Delete Action – Deletes the record and refreshes list
Workflow Action – Simple Workflow to send an notification e-mail to the Contact (this will only be visible if the Contact record has an e-mail, you can view more details on this in the following post: Power Apps Portals – Entity List: Conditional Action)
CSS
I am creating a CSS now that will perform the following actions:
Hide the dropdown button
Force the action menu to be displayed (without the dropdown button)
Force the menu items to be displayed inline (the same row)
Set the font-size as 0 so it will hide the text
Set the font-size only for the <span> element (which contains the icon) to 18px (you can always change this size if you want it bigger/smaller icons)
Set a different color for the hover event of the icon
For simplicity I am adding the CSS in the Web Page CSS section, but you could also apply this to the existing bootstrap web file, or create your own CSS web file.
Now by refreshing your page (remember always to clear the cache), you will have the following result:
Ok, great we have the icons there, but where has my Workflow action gone?
By default, Workflow actions (and a few others) doesn’t have an icon related to the action, for this reason our CSS is not working properly. If I inspect the element, I can actually see the action is there, but as it doesn’t have any icon, we are hiding the text and there is nothing to be rendered:
How do we fix it?
Simple enough, we need to add an icon to our action, we can do this in the Entity List options, by adding a <span> element to the button label property:
I am adding an envelope icon as my workflow represents sending an e-mail, but you can have a generic icon or anything else within the bootstrap/glyphicons: https://getbootstrap.com/docs/3.3/components/.
This is how my Entity List looks now:
Conclusion
I think this really enhances the user experience within an Entity List/Subgrid in the Portal, and the CSS method is a very simple implementation.
If your list contains too many actions, you might end up with a very busy web page and a poor UX. For this I will write a separate post using JavaScript, keeping the main actions as icons, and having secondary actions in the dropdown.
A special thanks to my colleague Jonathan Pavan that helped on this.
Hi, today I am going to talk about how to remove the Sort / Order By for a column within an Entity List in Power Apps Portals.
There are a few different ways on achieving that, I am going to show you a way using JavaScript/jQuery to change the element type representing the column header.
I am creating a simple Entity list pointing to the Active Contact view from my CDS environment, at this point all columns are sortable:
Now I am going to write a JavaScript code, where I am getting the column for the “Full Name” attribute (index 0) and replacing the <a> element for a <span> element.
I am adding this logic to the load event of the Entity List, to make sure it will apply if the user performs a sorting in the other columns, I am also validating the header name (aria-label) before performing the action, the reason for this is because once another load happens (a sort in the other columns for example), the index 0 for my list is now the Email column, which I don’t want to disable sorting in my scenario.
Code to be added in the JavaScript section against the Entity List record:
$(document).ready(function() {
DisableSort();
});
DisableSort = function() {
var list = $(“.entitylist.entity - grid”).eq(0);
list.on(“loaded”, function() {
var columnIndex = 0; // index of column you want to remove sorting
var columnName = “Full Name”; // name of column you want to remove sorting
var column = list.find(“table thead th a”).eq(columnIndex);
if (column) {
var text = column.attr(“aria - label”).trim();
if (text == columnName) {
column.find(“span”).remove();
var newElement = “ < span > ”+columnName + “ < /span>”;
column.replaceWith(newElement);
}
}
});
};
Now the column Full Name for my Entity List is disabled for Sort/Order By:
You could find better ways to retrieve the column index, this is just a simpler code to achieve a common requirement in Power Apps Portals.
In this post, I will show how to filter (display/hide) the Entity List Action options based on the record data with a Fetch XML filter:
Create an Entity List record – I am creating a simple entity list pointing to the Active Contacts view
Create an Action to your Entity List
I am creating a simple Workflow (On-Demand) to send an e-mail to the contact
Create a Web Page record to show the record Details
This will be a Details action
At this moment, if you test your Portal, you will see the two options available in the Action menu for each Item:
Now I want to make a validation against the record to filter my actions, in my case, as an example I will make the following validation:
If the Contact’s email field is empty
Hide the “Send e-mail” option
In the Entity List record, go to the Actions under Grid Configurations, select Advanced Settings and add a Fetch XML in the Filter Criteria (the Fetch XML must contain the header/basic structure, not just the filter):
Currently in Power Apps Portals, we can’t set a mask for a field, which usually improves a lot the UX. In this post I will show you how a simple example to achieve that using JavaScript/jQuery.
In my case, I am adding a whole number field to the Profile page/form.
Download the plugin and locate the jquery.mask.min.js file under the “dist” folder
Create a Web File in your CDS environment
Note that by default you can’t upload a .JS file, I am going to rename the file to .ES to bypass this validation (you can also change your environment settings but this is not recommended) – but keep the Partial URL as .JS
I am going to set the parent page as Home
I am going to set it to be hidden from site map and excluded from search
Adding JS library reference
We need to reference the JS, open your Web Page (content page) and add the following to your HTML “copy” field:
You can also add the above line to the “Tracking Code” Content Snippet, and this would be loaded in every page, in my example this JS would only be loaded in the Profile Web Page.
Adding the mask via JavaScript / jQuery
Still in your content page, navigate to the Advanced tab and add the following code:
Above I am using a placeholder to indicate the user what the expected format is, but this is optional, I could have the mask just as: $(“#ollie_wholenumber”).mask(“00000”);
Power Apps Portals provides us with very quick and simple ways to expose data from the D365 system into an external portal. Often, we have requirements to export or print the data using current Word Templates present in D365, but unfortunately there is no OOB feature (currently) for performing this task.
In this post, I will describe what is available using the OOB configuration from the portal, and how to extend it in order to export the data in the application. The idea of this post is not explain the Portal objects (Web Template, Entity List etc), you can find content on the Power Apps Portals on the following link: https://docs.microsoft.com/en-us/dynamics365/portals/configure-portal
For this demo, we will be using the following setup:
Power Apps Portals Starter (Version 9.2.2.15)
Before going to the step-by-step, below you can see what we will be achieving by going through the end of the post:
As a starting point, we will create an Entity List and Web Page record to present a list of the Active Contacts:
This is how the list will be rendered by default in your Portal page:
For Entity List records, we have the option (OOB) to add an Export to Excel button, this can be achieved by:
Open your Entity List record
Navigate to tab Options
In the Grid Configuration add a “Download” action and add a label
This is how the button is shown on the Portal, and once clicked, you will download an Excel file with the list content:
Unfortunately, this excel file is rendered just like our Advanced Find Export to Excel feature, which is not bad, but usually when we have a Website, we (and our customers) want this information to be presented in a friendlier way.
So now, we are going to the fun part, let’s extend this by creating our custom “Print Button”, which will use the standard JavaScript function to print a Page.
Now create a new Page Template and Web Template and make sure to associate the new Page Template to your existing Web Page:
For the Web Template record, I basically copied the content from the OOB Web Template “Full Page” and removed a few lines, leaving only the condition that will render the Entity List.
At this moment, nothing has changed and our Web Page is behaving exactly the same way as before.
Now, we are going back to our recently created Web Template, and add the following:
Give a name for the Div that is holding your Entity List
Add the Button for printing (outside the div)
Add the JavaScript code that will actually perform the printing (in the .JS code, I am actually creating a new HTML document, so we need to reference the .css here)
What I am also going to do, is add a new hidden DIV in the page with a custom logo (just create a Web File and upload your Logo in the notes), we can play around with showing/hiding the DIVs as we want in the JavaScript function, just make sure to set it up back to normal before the user closes the print window.
Add DIV with logo inside your print DIV
Show the Logo before setting the HTML content, also hide the Command Bar which will contain your Search Box / View Selector / Create or Download button (in case you setup any of those)
After setting the HTML Content, Hide the Logo and show again the Command Bar
In the top of the HTML, before the <head>, add:
Now we have our Logo being shown only for the printed window, and we have the same layout as the Portal webpage.
The following is the final code for the Web Template:
You can also use the same implementation to any other Web Page in your Portal, this way you can, for example, create a custom Web Template for your entity, displaying the information the way you need and add the Print button, showing and hiding anything on the Web Page if required, like logos, sensitive information, etc.
Maybe in the future Microsoft provides us a way to export using Word or Excel templates, which would be a very nice feature.
I hope this post has been helpful to you and your Power Apps Portals implementation.