I have written about the use cases for embedded Canvas Apps before as well as given different examples of how to create an embedded Canvas App. Take a look here for an example of how to implement one of the use cases. In my presentation Deep Space in Power Platform I also have a detailed description about how to create an embedded Canvas App.
There is one part of the app that requires some extra attention though and that is how to make use of the form context, i.e. how to get the information from the record in the Model-Driven App to your embedded Canvas App. In this blog post we will look into the details for just that and I will highlight an issue I ran into when trying to make use of the context.
About the embedded Canvas App used in this example
First a few words about the example that we will use in this blog post. We will use the Trefle API again. In this blog post I described how to use a Power Platform Dataflow in order to get data from the Trefle API into the Common Data Service. Now we will look at how we can have an embedded Canvas App on a Plant form and in the Canvas App display images, we will get URLs for the images from the Trefle API. That means, in this example we already have an entity in the Common Data Service and for its records we want to display some extra information (images) that are not in the Common Data Service.
We could create a Custom Connector and make use of that connector directly in our app. Take a look at this blog post for more information about creating a Custom Connector. We could also use Power Automate and a flow in the background to get us the images. That is what we will do in this example.
Below is how the end result looks like. To the right we have an embedded Canvas App displaying images from the Trefle API. The data displayed in on the left section on the General tab is data located in the Common Data Service. When the embedded Canvas Apps loads, a flow is triggered and takes the Trefle Id from the record, asks the API for the images for that plant and returns it to the embedded Canvas App. The tricky thing here was that the ModelDrivenFormIntegration did not get me the Trefle Id at first. Read on – and I’ll tell you some work-arounds for it.
Please note – This is just an example and in a real solution you would have two different places from where you get the information. That is what I have here as well (Common Data Service and I use the Trefle API even though all information can be found in the Trefle API). A real world scenario could be that we have customers in the Common Data Service and we want to display some data on the customer form, data which comes from another system.
Creating the App
When you want to create an embedded Canvas App you have a form as starting point. In this case we have the main form for the entity Plant. Currently we need to switch to classic mode in order to add a Canvas App. Add a field which always contains data and we will bind the Canvas App to that field. Under properties for the field we choose Add Component and Canvas App. Clicking on the Configuration button will take us to the Power Apps studio and we get to create our app. Take a look at my other blog post (described in the beginning here) for more detailed steps and pictures.
We will use a gallery to display our pictures. We will create a flow which gets the picture from the Trefle API. We will store the pictures in a collection and let the collection be the source for the gallery. We will make use of the form context, from the record we want to get the Plant Id in order to let the flow make an HTTP request using the Plant Id and query the Trefle API for images related to the plant in the Common Data Service. We will make use of the URL’s (pictures) and display those pictures. Now we will take a closer look at the part where we make use of the form context.
The ModelDrivenFormIntegration control
When creating an embedded Canvas App we get an extra control compared to when creating a Canvas App that is not supposed to be embedded in a Model-Driven App. It is called ModelDrivenFormIntegration and it is what you need to use in order to be able to get some values into your Canvas App from the record currently chosen in the Model-Driven App.
When we write our formulas we can use this control and when we do that it means we can access information from the record currently chosen. Even though it sounds easy, it took me a while to figure out why I did not get what I expected when running my app.
What is tricky with the ModelDrivenFormIntegration?
What was not as expected? Well, even though I tried to get data from the record using the ModelDrivenFormIntegration control as described in the documentation and the record contained values, I did not get any values.
In my case I want to use it early, i.e. I want to get a value from the record when the Canvas App loads in the Model-Driven App so that I can run my flow with a parameter (value from the record) as input.
I tried to have my formulas both for the OnVisible property of the screen as well as on the RefreshData property of the ModelDrivenFromIntegration (not at the same time though). Running my Model-Driven App, opening a record from a view and navigating to the tab which contained my embedded Canvas App, I found out that the ModelDrivenFormIntegration control did not get me what I wanted. It gave me nothing better than me scratching my hair and desperately trying to figure out why it did not pass me the data, but empty values. Most likely the ModelDrivenFormIntegration had not been initialized when I tried to get the values.
ModelDrivenFormIntegration control according to the documentation
So what does the documentation say about how we should use the ModelDrivenFormIntegration control? How should we get hold on the data from the record? Let us take a closer look at this control. Trying to use it you can see there are two different properties which seems to get us the data from the record. “Item” and “Data”.
The documentation says do not use the property Data. Use the property Item instead.
Solutions – How to get the data when the app loads
So what to do then if you want to get the data from the record when the app loads and it seams as the ModelDrivenFormIntegration control has not been initialized yet?
Google told me that others had had this behavior for their embedded Canvas Apps as well. I noticed someone had solved this by adding a timer to the Canvas App, set the property AutoStart to true, Duration to 1000 (1 second), Visibility to false and then triggered the flow OnTimerEnd. It worked for me. But it seems not ideal to be using a timer in the long run. I hope for a better solution.
I got the advice from my former colleague (now Community friend ❤️) Stina Persson to use a different approach. The recommendation actually came from Microsoft but it was for some time ago. Would be VERY interesting to hear the recommendation from Microsoft about how to best solve this now.
Anyway, here is what the recommendation was a few months back. It was to set the formula on the RefreshData property of the Modeldrivenformintegration control. It was to use the “old way” of getting the data, i.e. the ModelDrivenFormIntegration.Data property and to use the First function as well, to use Lookup in order to get the record and to use Set to set a variable – the record – which could then be used to get the data. This approach still works for me as an alternative to having a timer. However, since it is seen as an “old” way it does not seam to be the best way.
With “old way” I refer to a blog post from the Power Apps blog. When the General Availability for embedded Canvas Apps was announced on the Power Apps blog on the 27th of June 2019 you could read about how it during the Preview period was recommended to get data from the context by using the ModelDrivenFormIntegration.Data property.
In the preview release, to access the host model-driven form record, makers used the ModelDrivenFormIntegration.Data property. Additionally since that was a list of records makers had to use the First function and access the record as First(ModelDrivenFormIntegration.Data).
You can also read in the documentation that you should “migrate” your embedded Canvas Apps created during Preview time according to certain recommendations, e.g. that you should replace First(ModelDrivenFormIntegration.Data) with ModelDrivenFormIntegration.Item.
One other interesting piece of information that can be found in the documentation is that the ModelDrivenFormIntegration control does not provide a value for fields of a related entity. In order to do that the recommendation is as below. There the documentation says that you can use ModelDrivenFormIntegration.Data and that this approach performs better. You can find all known issues and limitations HERE.
I will update this blog post when I find out more about the best practice for how to get the data from the record related to specific scenarios. For now, if you need to access data from the record when the app loads – use the timer or the ModelDrivenFormIntegration.Data approach.
To be continued…
Embedded Canvas Apps – Thoughts about improvements
I am sure that there are more to learn about this ModelDrivenFormIntegration control and I am looking forward to exploring it further. Until then, here are some other thoughts on my mind related to embedded Canvas Apps. If someone have input, please let me know, e.g. if this works better for you. This is what I have on my mind:
1. The section on the form on which you place your embedded Canvas App (the place where you start and you add a field to begin with), this section has the same size even though you resize the Canvas App. The end result would look better if it was adjusted according to the size of the Canvas App. I just registered this as an idea and hope we will see an improvement here.
2. The app takes a few seconds to load even though it is a simple app. If the app is to be used frequently by the end user it would be a much better experience if it was possible to speed up the loading part. But I assume Microsoft is working on this. You can always take a look at the Performance tips for Canvas Apps but still I hope for general improved performance for the part to load the Canvas App in a Model-Driven App.
To wrap things up: embedded Power Apps gives us a powerful way to work with data from other sources than the Common Data Service in our Model-Driven Apps and also to work with data that are located several relations away. I really appreciate this feature and I am very much looking forward to seeing future improvements and recommendations about best practices from Microsoft.
If you want to deep-dive into all the details regarding the ModelDrivenFormIntegration control, I recommend you to go to THIS PART of the documentation from Microsoft. The start page for embedded Canvas Apps is found HERE.
Thank you my friend Stina Persson for sharing with me the recommendation you got for some time ago and by that inspiring me to write this blog post.