PowerApps Portals: Liquid and JavaScript – Better Together!

PowerApps Portals offers two primary languages for customization: JavaScript and Liquid. This leads to confusion as to which technology should be used, and when – I’ll try to clear up some of that confusion in this blog post, as well as demonstrate that in many cases the best option is a combination of the two.

And before anyone comments, yes I know you can use C# in plugins, and virtually any language with something like a Companion App, but the main go-to languages for PowerApps Portals development are Liquid and JavaScript.

Server-side vs Client-side

The first thing to understand is that Liquid is a server-side language and JavaScript is a client-side language.

Server-side languages are executed by the server, and the browser only sees the results of its execution. On the other hand, the full source code for client-side languages are sent to the browser in plain text, meaning anyone can see what’s going on.

This means that if you are working with data that is sensitive, you might want to consider doing as much as possible in Liquid. For example, let’s say you are building an events registration system, and you only want users to be able to register if the event hasn’t hit capacity. However, you’d prefer not to share with everyone how many people are currently registered, or what the limit is. You can pull the data and perform a calculation to determine if a user can register, all within Liquid – all the user sees is the end result of the calculation, not how it was calculated.

On the other hand, JavaScript is a more sophisticated language which allows for more complex calculations. For example, the number of available math operations in JavaScript is higher than Liquid.

JavaScript also allows you to modify the DOM. While Microsoft is moving towards implementing much of the functionality in Liquid using Web Templates (which means it can be modified by Portal administrators), there is still a lot of functionality where customization is limited to what you can do in JavaScript.

Another consideration is performance. If your complex calculation can be done in either JavaScript or Liquid, would you prefer to offload that to the client’s machine, or do you want it done on the server?

Accessing CDS Data and Authentication

The primary way of accessing CDS (aka Dynamics) data is using Liquid – there are no out-of-the-box APIs offered by the Portal that are easily consumable in JavaScript (yet). Therefore, if you are wanting to read data, Liquid is your best friend, using techniques like the entities global object and the fetchxml tag.

Similar to accessing CDS data, Liquid is the best way to determine if the user is logged in, and if so, who they are.

Better Together

Since both technologies have their advantages, I find that often the best approach is to use both. That is, use Liquid to generate dynamic JavaScript.

Let’s say on your Open a New Case form, you wanted to customize the heading on the page to instead say “Open a New Case for [Contact Name]”. We need to use JavaScript to modify the DOM, but we need to use Liquid to get name of the current user. The JavaScript to accomplish this looks something like:

$(document).ready(function() {
	$('.page-header h1').html($('.page-header h1').html() + ' for {{user.fullname}}');

If you’re new to this sort of thing, the biggest challenge is thinking about what gets evaluated when. Many first timers might do something like this instead:

$(document).ready(function() {
	$('.page-header h1').html($('.page-header h1').html() + ' for ' + {{user.fullname}});

Notice that I’m using {{user.fullname}} like a variable, which may seem more natural. However, you need to remember that Liquid is evaluated on the server, and then sent to the browser. The browser sees the output of the Liquid code. So the browser actually would see:

$(document).ready(function() {
	$('.page-header h1').html($('.page-header h1').html() + ' for ' + Nicholas Hayduk);

The above code contains syntax errors. Instead, if we go back to the original snippet of code, it would output the following:

$(document).ready(function() {
	$('.page-header h1').html($('.page-header h1').html() + ' for Nicholas Hayduk');

That is syntactically correct JavaScript.

One trick that might keep this straighter is to declare a variable, and initialize it to a value using Liquid, like so:

$(document).ready(function() {
	var name = '{{user.fullname}}';
	$('.page-header h1').html($('.page-header h1').html() + ' for ' + name);

Again, a common mistake when using that technique is to not wrap the Liquid in quotes, which produces incorrect syntax.

Using this technique, you can get quite sophisticated. One technique I use a lot is to use the fetchxml Liquid tag to get a list of entities, then I use a Liquid for loop to output a JavaScript array. Fellow Business Applications MVP Colin Vermander provides a great example in his blog post on Dynamics 365 portals: Use liquid to return JSON or XML.

Caution: there are certain situations when Liquid in the Custom JavaScript on Entity Lists will not get evaluated. See this blog post for more information.

Liquid Debugging

Debugging Liquid code is a question that has come up multiple times on the Microsoft Dynamics Community forums (as examples, there is this thread and this thread).

Unfortunately there is no simple answer. Since it runs server-side, and we don’t have access to the servers that Microsoft uses to host the Portal, we can’t step through Liquid code. Instead, we have to rely on insert logging messages into our Liquid code. But again, since we don’t have access to the server, where should we log to? This is where JavaScript helps us out.

By inserting console.log() or alert() statements throughout our Liquid code, we can get more details on what’s happening. Remember to wrap your console.log or alert statement in script tags if your Liquid isn’t in a Custom JavaScript attribute.

Building on the example from above, I can do something like:

$(document).ready(function() {
	var name = '{{user.fullname}}';
	$('.page-header h1').html($('.page-header h1').html() + ' for ' + name);

Again, don’t forget to wrap your Liquid code in quotes, as typically you want to pass strings to console.log or alert.

3 responses to “PowerApps Portals: Liquid and JavaScript – Better Together!”

  1. […] post PowerApps Portals: Liquid and JavaScript – Better Together! appeared first on Engineered […]

  2. Serge van den Oever says:

    Can you explain how to include JavaScript or link to a JavaScript file in PowerApps Portals, seems to be possible from within a form, but would like to do it outside a form, and for example be able to include ReactJS and custom code.

    • Nicholas Hayduk says:

      Hi Serge,

      You’ve got a few options.

      For external library hosted on CDN, you can include references directly to them using script tags.
      Or, you can upload them as web files, and then reference their URL in script tags.
      Or, you can include the JavaScript in a web template, and include the Web Template on the page using the Liquid include tag.

      For larger libraries, the last option is less desirable, because you won’t be taking advantage of the caching of JS files.

      Now, the next step is to figure where to include your

Leave a Reply

Your email address will not be published. Required fields are marked *


Engineered Code is a web application development firm and Microsoft Partner specializing in web portals backed by Dynamics 365 & Power Platform. Led by a professional engineer, our team of technology experts are based in Regina, Saskatchewan, Canada.