Skip to content

Common mistakes to avoid when creating your first Canvas Power Apps

I see quite a lot of Canvas Power Apps made by others. It’s really helpful. You often learn something new from them. At the very least, you’ll be amazed at how different ways things can be done.

I can see the authors’ first and second Power Apps. I’ve noticed certain techniques and quirks recurring in them. This time we will go through them a bit.

I want to emphasize that these are not mistakes or stupidity. The solutions worked perfectly. However, the same thing can be done more efficiently, more maintainably, with less code or otherwise just more elegantly.

And yes. In my first Power Apps, I did things using exactly these same special methods.

Useless LookUps

You shouldn’t do those great LookUp commands in vain.

We have a list of customers (Accounts) in the gallery and we want to display the customer number of the selected customer next to the list. We use a formula for this

LookUp(Accounts, 'Account Name' = galAccounts.Selected.'Account Name').'Account Number'

We now use the LookUp function to search for the customer’s information in vain. They have already been applied to the gallery. We can refer to all the data in the gallery row.

galAccounts.Selected.'Account Number'

The same operating model is often seen elsewhere. We already have the row information retrieved. But for some reason on a different side of our application, we are fetching them again.

The reason is often that the gallery or variable for some reason does not have a value for all the fields in the row. Even if it should. We decided to retrieve the data again with LookUp to get the missing value.

Why aren’t the values ​​of all the fields in the row always available to us? The reason is most often in the optimization performed by the platform. It interprets that we don’t need that field, which is why the value is not included when retrieving information.

In this case, instead of an extra LookUp, you should do something else. For example, turn off the following optimization, so that the result set always includes all fields.

Mysterious With

Extra LookUp functions can also be easily eliminated using the With function.

We want to display the customer’s hometown and country in the text field in the form “City (Country)”. Easy! Let’s create a string with

  • customer’s city (searched with LookUp )
  • characters ” ( “
  • customer’s country (searched with LookUp )
  • sign “)”
LookUp(Accounts, 'Account Number' = "500").'Address 1: City' & 
" (" & 
LookUp(Accounts, 'Account Number' = "500").'Address 1: Country/Region' & 
")"

But… We make two queries to the Dataverse. First, we search for the city and immediately after the country. This can be done smarter with the with function. The idea is that the necessary lines are first searched for in a temporary variable. After this temporary variable can be used when performing operations.

So in our example

  • the customer’s information is retrieved in a temporary variable (varMyAccount)
  • a string is entered using the data of the customer searched for in the variable
With(
    {varMyAccount:LookUp(Accounts, 'Account Number' = "500")},
    varMyAccount.'Address 1: City' & " (" & varMyAccount.'Address 1: Country/Region' & ")"
)

In this way, we retrieve the customer’s information from the database only once.

Useless variables

Very often in the application, you come across a variable that tells you whether you are viewing, editing or creating a line on the form.

For example, let’s open the form screen in editing mode.

ViewForm(SettingForm);
Navigate(SettingFormScreen);
Set(varMode,"View");

Or let’s move on to create a new line.

NewForm(SettingForm);
Navigate(SettingFormScreen);
Set(varMode,"New");

The varMode variable is completely unnecessary. You can check the status of the form directly from the form.

  • SettingForm.Mode = FormMode.View -> We are viewing
  • SettingForm.Mode = FormMode.Edit -> We are editing
  • SettingForm.Mode = FormMode.New -> We are creating a new one

The same can be seen in other contexts as well. We create our own variables, even if the same result could be reached without them.

Every new variable is a place for human error.

Global variables

There are two types of variables in Power Apps. Global and local variables. Many use only global variables.

Set(gblMyName, "Timo")

The global variable is available on all screens of the application, when the application starts (App OnStart), and in components if you have allowed it. Using them is easy when you don’t have to think about it anymore.

But they are performance nuts. The platform has to wade through all the screens when the variable value is updated.

You shouldn’t use global variables unless you have to. Otherwise, local variables (Context variables) should be used.

UpdateContext({locMyName: "Timo"})

A local variable can only be used within one screen. Often that’s enough.

A temporary variable defined inside the With function can be thought of as a third type of variable. It can only be used inside a with clause.

Use of groups

Groups are a way to bundle controls used in Power Apps together. For example, a text field and its associated title.

Smart in principle, but these grouped controls are really painful to modify. Inadvertently, all the controls in the group will be modified, when only one should have been modified. Or moved them all, when only one had to be moved.

Groups are a relic of a time when nothing smarter was available. Today, it is advisable to use containers for this.

They are easier to work with. The position of the controls inside the container is always relative to the position of the container itself. New containers (Horizontal/Vertical container) can be used to build responsive applications.

Repeating the same controls

Navigation is an excellent example of unnecessary repetition of controls. Typically, each navigation element has its own button.

If we want to round the corners of the navigation elements or change the color, the changes must be made for each button. If we want a new point in the navigation, we have to add a new button to the screen.

It is smarter to implement the navigation as a gallery. After that, the changes to the button are made into one repeated button within the gallery. Adding new elements is also easy.

If the navigation is used on several screens, it should still be implemented as a component.

All changes made to the navigation are implemented in the component. The changes are immediately visible wherever the component is used.

The same code in many places for no reason

Sometimes you come across situations where the author may not have been quite sure how things work. Just to be sure, the same commands have been put a little everywhere.

For example, a list of customers.

When a row is selected from the gallery, we go to edit it (Navigate). At the same time, the form is set to editing mode (EditForm) and initialized (ResetForm).

EditForm(frmAccount);
ResetForm(frmAccount);
Navigate('Accounts Screen') 

If the new button is pressed on the screen, the same is done with the difference that the form is set to create mode (NewForm).

ResetForm(frmAccount);
NewForm(frmAccount);
Navigate('Account Form Screen')

But what is done with the form when the user presses the back button?

Let’s initialize the form before moving back.

ResetForm(frmAccount);
Navigate('Accounts Screen')

This initialization is pointless, as the form is initialized on the customer’s screen always before moving to the form.

Actually initializing the form is pointless there as well. The form is automatically initialized when its mode is set (NewForm and EditForm).

The commands on the client screen would be enough for us (when going to edit):

EditForm(frmAccount); Navigate('Accounts Screen') 

And when moving to create a new line:

NewForm(frmAccount); Navigate('Accounts Screen')

All you have to do with the back button on the form is to navigate back.

Dependencies between displays

It is not a good idea to refer to the controls on other screens from the screens. This creates a dependency between screens and thus complicates the optimization performed by the platform.

But it can also cause weird situations. Attached is an example of living life.

We have a screen where you can maintain links to various documents. One of these is the application manual. The links are stored in Dataverse.

There is a button on the start screen of the application from which you can open the user manual.

Download(inpHelpURL.Text)

However, pressing the button gives an error.

With a second press, the help opens. What is really going on here?

The button refers to a field that is on the second screen. The value of the field is fetched from Dataverse. The platform desperately tries to optimize when the field value should be fetched. That you don’t seek it in vain. In this scenario, the optimization goes wrong and the value of the help link (inpHelpUrl) does not exist when the download function is already executed.

Optimization can be turned off in the settings (Delayed load). After this, the implementation works again.

Another option, of course, is to get rid of dependencies between screens.

Power Apps

Leave a Reply

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