Author Archives: Alex Shlega

Canvas Apps: What is a “scope” and, what does it have to do with Filter/Lookup functions?

In the previous post, I was looking at which attributes are added to the CDS query by the Filter/Lookup functions. Might not end up with a definitive answer there, but, to summarize, chances are you’ll get the attributes included IF those attributes are utilized in the other formulas.

Now, it turned out there is a caveat to the statement above.

Somehow, this is also tied to the record scope. In the example below, I have a label that’s displaying a text from the variable. That variable is set from within a button “OnSelect” in the gallery or from within another button “OnSelect” outside the gallery. Both “OnSelect”-s are using exactly the same formula:

Set(SelectedContact, LookUp(‘Contacts’, txtSearch.Text in ‘Full Name’ ));

and here is how label’s text is set:

“Selected Contact: ” & If(IsBlank(SelectedContact), “Blank”, SelectedContact.’Middle Name’)

As you can see below, the result of those clicks is quite different (just watch the label):scopes

Actually, when using that “in-gallery” button, apparently I’m not getting anything at all (not only the attribute, but even the record itself is not retrieved).

Why?

Again, I don’t have a complete explanation, but this is definitely related to the scopes. Because, you see, once the formula for that in-gallery button is updated to use disambiguation operator (“@”), I am starting to get the record (without the attribute yet).

Here is the updated formula:

Set(SelectedContact, LookUp([@’Contacts’], txtSearch.Text in ‘Full Name’ ));

Here is how it looks like now – notice that SelectedContact is not blank anymore, even though there is still no attribute value:

scopes1

Now, if I add that attribute to the formula (just about anywhere), I’ll finally start seeing it retrieved from the datasource. Here is another version of that formula (for the in-gallery button) – this may be the most important part of this post, btw:

image

And here is another recording:

scopes2

Finally, both buttons are working the same way.

So, what was the problem with the first version of my formula? Apparently, since I am using the gallery to display contacts, and since I am using a Lookup function to work with the same datasource, somehow those two are getting into a naming conflict. A disambiguation operator allows me to use global scope for the data source name:

image

https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/functions/operators#disambiguation-operator

However, even with that, and probably since it’s happening in a different scope, that in-gallery Lookup call does not know which attributes should be added to the request, and I have to mention all those attributes in the same scope.

And, of course, it’s just me reflecting on the ad-hoc workaround, so, even though it seems to make sense, I am not sure I’ve covered everything. What’s more important, I am still not sure of the exact “method” the framework is using to identify the attributes which will be added to the CDS query (but, at least, it seems I know, now, how to force it to add those attributes if some of them are missing).

 

 

Canvas Apps and CDS: Which attributes are added to the query?

Before you start reading, here is a disclaimer right away: this post is not an extension to the power apps documentation. It is just my attempt to figure out how Lookup and Filter functions work in Canvas Apps when those functions are applied to the CDS data source. I am hoping the information below is accurate, but use it at your own risk.

Was it scary enough?

Let’s continue to the fun part, then.

Here is a question: when you have a Filter function in your canvas apps against “Contacts” entity, which attributes will each of the returned records have?

Luckily, Canvas Apps are still web apps, so I can fire up chrome dev tools and do some network tracing.

But, first, let’s talk about the setup.

I have a simple Canvas App that’s using a Gallery control to display contact names and email addresses. There is a text box where I can enter a keyword, and that keyword will be used to filter records in the Gallery:

image

image

Now, I’m using “Select” button to set “SelectedContact” variable:

image

In turn, I’m using that variable to display selected contact phone number:

image

Based on the setup above, I have “Contacts” datasource in my app:

image

However, if you look at the above screenshots, I am not specifying the query attributes anywhere. There is no FetchXml, there is no Column Set (for those of you familiar with the SDK), there is no “select” parameter (Web API?), etc. So how does the framework know that it needs to query Phone Number attribute, for example?

Quite frankly, I don’t knowSmile But I can guess.

When looking at the query that the app sends to the Web API endpoint once the search keyword is updated, I see this:

image

Apparently, this includes all the fields I’m using on that screen. Let’s try something , though. Let’s replace ‘Home Phone’ with ‘Middle Name’ in the label’s text formula:

image

If I just “play” the app right away, there will be no text displayed in the label:

image

However, if I change the search text so a new request is sent to the server, and, then, click “select” button for exactly the same contact, here is what I’ll get:

image

What happened? From the dev tools trace, it’s clear that ‘Middle Name’ attribute was added to the query:

image

Although, ‘Home Phone’ (telephone2) is still there as well.

Hm… Let’s close the browser, completely. Then let’s open it again and re-run the app. Here is how the trace looks like this time:

image

There is middlename, but there is no telephone2.

I think at this point it’s clear what the framework is doing. It’s looking at all the attributes you might be using in different places, and it’s adding them to the query. Those attributes stick to the session, so, if you stop using some of them, they will still be added to the query until there is another session, at which time the framework will update the list of attributes.

However, there seem to be some optimization there, and it might be unexpected. What if I used Filter in a different place to populate a different collection?

image

Since my app is not using other attributes through that collection, only contactid and ‘Full Name’ attributes get added to the query:

image

Now what if I take it one step further?

image

Technically, I seem to be doing the same what I was doing before. I am setting “SelectedContact” from the collection, so I would expect ‘Middle Name’ to show up in the label text. Instead, that label does not show anything now:

image

Hm…

How about I collapse that formula into a single line?

image

Now I’m getting somewhere, it seems:

image

Except that… My label is absolutely empty now:

image

I need to go there, update the “Text” property of that label, and, then, the text shows up:

image

Fortunately, this only happens once when following the steps above.

Still, the fact that I have to collapse my formula into a one liner means that the framework has limited ability to infer the attributes it needs to add to the query.

It seems that, as soon as the attribute is utilized “directly”, everything works. But, once there is an extra variable between the query and the place where that attribute is utilized, this mechanism stops working. For example, it stops working once “OnSelect” formula is modified this way:

image

Which is obvious from the dev tools – there is no “middle name” attribute there:

image

Does this provide a definitive answer? Not really, but, quite frankly, I’ve been struggling with this behavior in my application recently, and, so I figured it would make sense to dig into it and see what’s happening. Not sure if it helps at the moment, but… knowledge is power, tooSmile

PS. There is a continuation to this post here: https://www.itaintboring.com/powerapps/canvas-apps-what-is-a-scope-and-what-does-it-have-to-do-with-filterlookup-functions/

Canvas App: Incompatible variable types

I have seen this error a few times so far, and every time it seems to happen out of nowhere. My application used to work – I even recorded a video of how it was working the night before to share it with the client. Lucky me, since, when I opened it the next morning to do a demo, all my formulas were showing errors similar to the one below:

image

“Incompatible type. We can’t evaluate your formula because the context variable types are incompatible with the types of values in other places in your app.”

Looking at the list of variables, I noticed that CurrentContact is of the “Error” type:

image

Not that it was very useful, but, to make it somewhat worse, I also found a different screen where the error was a little more precise:

image

If you’ve seen it before, maybe you can leave me a note since I’d be really interested to know what’s happening there. At the moment, I only have a workaround which seems to help, but what bothers me is that it does require quite a bit of application refactoring. Basically, I have to rename the variable everywhere. Will this problem happen again later when my app is bigger and it takes longer to do the renaming?

In the example above, I started to change variable name, and I’ve noticed quickly that the error was gone. So, I tried renaming it back to the original, and it was still all good. However, I remember the same issue happened to me before, and I actually had to change the name of my variable on a few screens before the error was gone.

Anyway, so far so good. If you run into it, you may try the “renaming trick”. But, if you have a better solution, please let me know.

A Canvas App as a Kiosk App?

I was looking for a point of sale software solution the other day, and it occurred to me that, in theory, I could probably write something up using a Canvas App. Of course I would need to solve a few problems, such as:

  • Which device do I run it on
  • How do I stop users from using other system functions
  • How would licensing work

 

And there might be a few more, but those are the main ones.

Here is what I ended up with:

How does it work?

Basically, there is a windows application that’s hosing my canvas app. It’s using Chromium engine, so it seems to be fully capable of running Canvas Apps. Although, if it sounds as if I had to create a new “Edge” browser for this purpose, that’s a bit of an overstatement. Sure, I had to write a few lines of code in C#, but here is what I used:

https://github.com/cefsharp/CefSharp

That’s a nice open-source library that allows us to embed Chromium in .NET apps.

The rest is all about running that .NET app in a full-screen mode, so that the task bar is hidden and the app stays on top of all other windows. Besides, that app can’t be closed using “Alt+F4”, for instance. Whoever is trying to close it will need to provide a key phrase.

Of course this all means that, should I start using this app, I’d need to run it on a Windows 10 laptop/tablet.

And what about the licensing? This application still requires a login, so, in the scenario where an agent would login in the morning, that agent would have to be licensed of course. Then the client might come in, sign a document, submit it through the app. And another client might come in to do the same. And then another one… this scenario would not be so different from when the agent would just hand over this tablet/laptop to each client manually for signatures, and that would be absolutely fine licensing-wise.

Either way, if this is something you’d like to explore a little more, here is a github repo you might use as a starting point:

https://github.com/ashlega/ItAintBoring.KioskApp

By the way, you’ll also find that PI Catcher canvas app there:

https://github.com/ashlega/ItAintBoring.KioskApp/tree/master/CanvasAppSolution

Have fun, and have a great upcoming Pi day!

Power Automate Flow – creating an email with attachment in CDS

  The way I feel about Power Automate Flow is a perfect example of the love-hate relationships. Yes, I can do much more than I used to be able to do in the classic workflows. However, every now and then I run into something that seems simple, but that ends up being an exercise in google searching, forums browsing, intuition-based Flow development, and, of course, in the intense self-control.

  The subject of today’s exercise was the following question posted in the community forums:

https://powerusers.microsoft.com/t5/Building-Flows/How-to-use-flow-to-send-CRM-email-with-attachments/m-p/494318#M61306

  Well, this seems simple, and it is sort of simple once it’s been done, but it took me a while to figure out how to do it.

  Here is how the Flow looks like:

image

There are a few things to consider:

  • I can create an email record using “Common Data Service (Current Environment)” connector
  • Once an email record has been created, I need an HTTP (Azure Ad) connector to add an attachment
  • And, finally, I need an HTTP (Azure Ad) connector to send the email created earlier

Why do I need those Http with Azure Ad connectors?

image

This is because I could not figure out how to add email attachments/send emails directly through the CDS connector (and there were a few helpful links in the community forums which came up when I was looking for a solution. For example, this one has really helped: https://community.dynamics.com/365/f/dynamics-365-general-forum/360013/creating-activitymimeattachment-email-attachment-record-through-microsoft-flow).

With those connectors, however, you have to use a connection which is using correct base url. For example, in my case here is how “Send the email” step looks like – notice the request url:

image

In order for this to work, you’d have to create a connection so that base resource url and azure ad resource url would match the request url above:

image

image

Also, do keep in mind that all references are supposed to be in the following form:

/entityset(guid)

image

With all that said, let’s just see how each step in my workflow is implemented:

1. Loading the file from Sharepoint

image

2. Creating an email (using “create record” action of the “Common Data Service(Current Environment)” connector)

I’ve hardcoded contact guid there, but you might, as well, get it from CDS using “List Record” action, for example

image

3. Converting email message id into “any” type – that’s a Compose action

image

This is so I could use it in the next step

4. Creating an email attachment (Http with Azure AD)

“Outputs” is from Get Email ID above

That base64 function is an expression: base64(outputs(‘Get_file_content’)?[‘body’])

I’ve also hardcoded file name & mimetype

image

5. Finally, sending an email (Http with Azure AD)

image

That’s it. Done. I think in the end I love Flows! Since, of course, I would not even be able to load that file from Sharepoint using a classic workflow, so I’d have to write some code, and it would take me quite a bit longer to figure out Sharepoint authentication etc.

Verifying application type in the PCF component

You probably know that PowerApps Component Framework is now in the public preview for CanvasApps. So, what do we do when there is something new? Of course, we start poking around to see what happens.

One thought that kept bothering me is that I tend to use more than I am probably supposed to in my components. For example, my N:N Lookup control is using Xrm object, and, technically, it should not. But, on the other hand, since it’s always going to run in the context of the model-driven form, and Xrm is supposed to be there, there should be no harm. Right?

Well, kind of. Turned out I can, as well, just add that component to a canvas app. Inevitably, it will fail, so here is how it will look like:

image

That’s not so nice, after all.

Ideally, I should be able to somehow identify the target of my component – should it work with model-driven/canvas/or both types of applications? Unless I’m missing something, and I’m guessing that kind of setting should be part of the manifest definition file, here is an idea you might vote for if you think it makes sense:

https://powerusers.microsoft.com/t5/Power-Apps-Ideas/Add-target-application-type-canvas-model-driven-both-to-the-PCF/idi-p/493354#M29919

In the meantime, I was looking for a way to add some code to the component so it would display more user-friendly message. Which, in itself, should not be a problem. Figuring out current application type turned out to be a little tricky, though, since some of the properties I would expect to become unavailable in the Canvas Apps are, actually, still there. It seems specific values of those properties don’t necessarily make sense, but the fact that they are there makes it impossible to compare some of those properties to “null” if I wanted to do different things depending on the outcome of that comparison.

For instance, this screenshot is for a Canvas App, but notice entityTypeName there:

image

Having said that, I just settled on the most simple thing to do that kind of comparison (which I alluded to above):

if(typeof Xrm == 'undefined'){
   this.errorElement = document.createElement("div");
   this.errorElement.innerHTML = "<h2>This control only works on model-driven forms!</h2>";
   container.appendChild(this.errorElement);
   this._isValidState = false;
}
else
{
    //Proceed as usual
}

 

Of course, in order to do that I also have to declare Xrm variable in my typescript to be able to build my component without errors:

image

It’s time for a quick test? Here you go:

image

As usual, the source code/solution are available from github:

https://github.com/ashlega/ITAintBoring.PCFControls

PCF components and setVisible / setDisabled

Every input control in model-driven apps has a couple of methods that I use quite often when creating web resources to customize form behavior. Those are:

 

Actually, I can’t recall a single projects where I would not need to use one, or, probably, both of those.

So, we have PCF now, and there are more and more custom controls. So how are those controls going to respond to a web resource calling one of those methods for them?

Actually, they respond pretty well, but there are a few things to keep in mind.

Init method will be called every time your custom PCF control becomes visible. It will be followed by  a call to updateView. This is similar to what will happen on load of the form. Below, I have Chrome dev tools open, and you’ll see how calling “setVisible(true)” causes my PCF control to go through both “init” and “updateView” methods:

setvisible

Actually, there is more to it:

  • Calling setVisible with “false” argument to hide the control does not kick off “init”/”updateview”
  • Calling setVisible with “true” argument to show and already visible control does not kick off “init”/”updateview” either (apparently, there is some optimization)

 

As far as “setDisabled” goes, whether it’s called with “true” or “false” as an argument, it always results in a call to updateView:

setdisabled

However, what if I hide my control first? In that case, my custom PCF control stops responding to just about anything. For example, calling “setDisabled(true)” goes absolutely unnoticed until the control is visible again:

setdisabledwhenhidden

And here is a diagram that may help:

image

 

 

 

A PCF-based regex validation for a regular out-of-the-box control

You know how we can put more than one control for the same attribute on the model-driven form? So I was thinking… would it work if I added the same attribute twice, but if I used default control for the first occurrence of that attribute on the form, and, then, if I used a custom PCF control for the second occurrence? Not only that, though. What it I could hide that second control, and, instead, use it for validations only?

This was based on the idea that whenever the attribute value changes(no matter how or through which control), the framework would call updateView method for my PCF control, and that’s where I could do the validations.

Here is how it worked out – keep in mind there are no web resources attached, and all I had to do to add that extra validation to the default “name” field is to configure a custom control for the second occurrence of that attribute on the form:

externalvalidator

That approach is, actually, pushing the boundaries of what’s “supported” because:

  • I need that second control to be hidden
  • However, if I hide it by default, my PCF control code would not run (guess that’s how the framework is)
  • So, I can’t hide it in the form properties, and I need to hide the HTML element containing my control. That part is not, technically, supported, but, well, consider this an experiment

 

With that said, what exactly are the steps for setting up an extra validation using this experimental PCF control?

1. For an field on the form, add the same field one more time

image

2. For the second occurrence of the field, configure custom control

image

3. Save, publish, and see how it works

A word of caution: since this control has to hide itself, it’s looking at a certain CSS class, and, as of right now, this may not always work (seems to depend on the form resolution etc). I may have to play around with this “hiding part” a little more to make it more reliable.

Or, if you want to try it yourself, just get this solution from github and see how it works out:

https://github.com/ashlega/ITAintBoring.PCFControls

Power Apps Component Framework (PCF) – is it complicated? Or is it not?

Ever since Power Apps Component Framework went into the GA, there probably was not a day when a new PCF component would not be released by somebody in the Power Platform community.

There is just no way to ignore the fact that PCF has turned into a very popular addition to the Power Platform developer toolset.

And it’s not like it’s just a toy for developers to play with – in these few months I personally saw a few situations where PCF components were developed on the actual projects because they do provide the best level of re-usability and/or configurability when it comes to the UI components in Power Apps.

However, there is something very unique about PCF component development which makes it difficult to clearly answer the question of whether it’s complicated or not.

What is PCF to start with? From my perspective, it’s, basically, plumbing. PCF itself is not a component – it’s an agreement on how PCF components should be developed. There are command-line tools, there are a few standard event handlers, there are a few standard data types, there are some out of the box javascript functions and objects to facilitate execution of standard operations, there is a manifest definition file, and there is a bunch of sample components which anyone can use to start developing their own components quickly.

That may seem like a lot, but it’s, really, not.

Any plugin developer will tell you that the number of things one needs to learn to efficiently develop plugins is, likely, even greater.

Still, I’ve done PCF development, and I’ve done plugin development. If you ask me, PCF component development is way more complicated. Although, if you ask a seasoned front-end developer, they’ll probably say PCF is the most simple thing they had to learn lately.

Here is how I see PCF development:

The more experience you have with the frameworks/tools/technologies in the orange circle, the easier it will be for you to develop PCF components. Since, really, PCF component development is not so much about knowing the PCF framework – it’s still about creating a user interface widget with javascript/typescript, and PCF is nothing but a plumbing which connects that widget to the underlying model-driven/canvas screen.

In the same way, plugin development looks like this:

In general, it may take longer to figure out “plugin development framework”, but, once you’ve learned it, you can rely on your C#/.NET development experience to start creating useful plugins.

In other words, if you are thinking about developing a PCF component, you may want to do a mental exercise. Imagine that you need to develop a typescript/javascript application that will do what you think your PCF component should do. With PCF taken out of that equation, at least temporarily, do you think you’ll be able to do it? If the answer is “piece of cake”, you are in a really good shape. Just be prepared to spend a day or two working through the documentation, and you’ll be good to go.

If, however, the answer is “no idea – I thought PCF would take care of it”, that’s where you’ll quickly find out that PCF is not a magic bullet, and you may still need to learn front-end development first.

And that’s when you decide if PCF is complicated or not…

Making a PCF control readonly

Up until now, none of my PCF controls were meant to be readonly. But, of course, it would only make sense to prevent updates for inactive records and/or when some of those controls are set to be readonly in the form designer:

readonlypcf

Dynamics Ninja has already described the basics in his earlier post: https://dynamicsninja.blog/2019/11/25/is-your-pcf-control-read-only/

Just to reiterate, though, we can use the property below to decide whether our PCF control should be readonly or not:

context.mode.isControlDisabled

However, depending on how that PCF control is implemented, making it readonly might end up being a bit more involved exercise.

For both N:N treeview and N:N dropdown controls in my PCF controls solution, I ended up using the following approach (and, it seems, it may work for other controls, too):

  • There would be a transparent overlay div element
  • That div element would only become visible once isControlDisabled has been set to true

From the HTML/CSS standpoint, for this to work I would actually need 3 elements:

  • A container div (which could be the container element provided by the PCF framework)
  • An overlay div added as a very first child element to the container above
  • Main PCF component element

For those 3, I’d be using the following CSS styles:


.pcf_container_element
{
	 position:relative;
	 width:100%;
	 height:100%;
	 overflow:none
}

.pcf_overlay_element
{
	 width:100%; 
	 height:100%;
	 border:0px;
	 background-color:transparent;
	 z-index:10;
	 position:absolute; 
	 top:0;
	 left:0
}

.pcf_main_element
{
	position:relative; 
	top:0; 
	left:0
}

With these settings, my overlay element would be placed just on top of the main element, so there would be no way to click/change anything in the control. And, yet, since my overlay element would have transparent background, it would no be visible to the user. Which means this would all result in a read-only PCF component presented to the user.

You can take a closer look at the code in the github repository, but here is the summary:

setReadonly function will change visibility of the overlay element depending on what’s stored in the isControlDisabled property

public setReadonly(): void
{
(<HTMLElement>this.container.firstElementChild).style.display = this.contextObj.mode.isControlDisabled == false ? "none" : "block";
}
</HTMLElement>

In the “init” method of the PCF
control, all those elements will be created with correct styles


	container.classList.add("pcf_container_element");
		
	this.overlayDiv = document.createElement("div");
	this.overlayDiv.classList.add("pcf_overlay_element");
	container.appendChild(this.overlayDiv);
		
	this.mainContainer = document.createElement("select");
	this.mainContainer.id = this._ctrlId;
        ..
	this.mainContainer.classList.add("pcf_main_element");

Those 3 css styles will be added to the PCF control through an additional css resource file

image

Finally, setReadonly function should be called from somewhere

It should definitely be called from the updateView; however(and maybe that’s something I need to look into a bit more), I found that for my N:N treeview control updateView does not get called on the initial load, for example. Therefore, I’m also calling it once the treeview has been initialized.

That seems to be all there is to it. And, of course, those css styles above can be tweaked a little more. For example, you might want to add background color to the overlay element. In that case it might make sense to use rgba colors to make the background transparent.