Component Actions, what are they?!

Component Actions, what are they?!

Photo by Pixabay: https://www.pexels.com/photo/person-riding-bike-making-trek-on-thin-air-71104/

In a previous article, we took a look at one of the new property types of components called Functions. Today we're going to look at Actions, which are eerily similar to Functions 👻


I'll admit that it's taken me longer than I'm willing to admit to get my head around the purpose of actions, the description given by Microsoft it a little... weird.

This type of property can be called as a function with parameters, and can contain logic that changes state (side effects).

So we can call an action like a function, and pass parameters in. All good. But side effects? What's that?


So, side effects then?

Side Effects in PowerFx seem to have a broad meaning; There are two popular functions that have "Side effects":

Select(), and

Reset()

Select() will simulate a selection of a control (Generally, any that have an OnSelect() function). Reset() will, well, reset a resettable control.

But also, SubmitForm() hass a Side Effect, rightly, because it affects your Edit Form's datasource, or the record passed in.

Now, the current documentation for Action Properties suggests you can update a datasource, but from what I can ascertain; this isn't currently working. I've raised an issue on the documentation repo and will update this when I hear back.

So what we're saying with Actions, is that we can trigger Side-Effects within our components of controls within our component. I'll lead by example:


So with that, let's make an Action...

There's a business requirement to track when a crab has graced us with their pincers 🦀. I need to be able to grace our component by either:

  • Selecting the button in the component.

  • By selecting a special button that isn't in our component.

This will be fairly straight forward, we have a component configured with a button and label as below:

No alt text provided for this image

The button code isn't much, we're going to increment a variable within the component by 1 with each pinc.. click.

Set(gvClicks, gvClicks + 1)

With a label to show the results. And.. as you would expect...

No alt text provided for this image

So Action Property Types come in when we want to trigger the Select() function of the "Click Me 🦀" button within our component from the App scope.


It's about time we made an Action!

Create a property in the component as follows:

No alt text provided for this image

Note: If you can't see the additional property types, you'll need to enable Enhanced Component Properties from the Settings menu, you'll want to ensure you have "Enhanced component properties" from "Settings" > "Upcoming features" enabled.

The code we're going to add is simply going to Select the button:

Select(btn_GracePincer)

Next, we'll need to add our component to a screen so we can Call this Action:


Call the Action

No alt text provided for this image

I've added a telepathic button to the app, along with the component itself.

We can use the "Telepath Pincer" button to call the Action in the Component below (in pink, or orange, or a mixture of the two?).

The OnSelect property of the top button should just call the action as follows:

cmpPincer.GracePincer()

The result is the code in GracePincer() is triggered, which Selects the "Click Me" button within the component, thus our pincer counter continues to climb.

No alt text provided for this image


So... why?

Okay, we don't all work with Crabs. But there is a reason Actions exist:

  • Components are resettable, but resetting a component resets all controls/variables etc in the components. Actions mean we can specifically target controls/variables etc when doing a reset.

  • Select() can't be used on components. So actions now give us a way to perform Select()-ish "Side Effect Formula" on components, and we can choose what is/isn't selected.

  • Once more, you get full access to the Component Scope, so you can add to collections, set variables etc, via the Action. So pass in a record as a parameter, and add it to the components collection! Here's an example below of a component that takes in a staff record (Name, Role and Photo) and adds to a collection within the component:


Collections and Records example

We have a property in a component called "Ingest Record", which takes a record as a parameter:

No alt text provided for this image

The component has a Gallery to display the contents of the collection colRecords.

The property above has the following code:

Collect(colRecords, Record)

We define the schema of Record with:

{ 
    Name: "Mike Gowland",
    Role: "Developer",
    Photo: SampleImage
}

And we can now implement the component in an app, and call IngestRecord, passing in a record that matches the above schema for the Record parameter:

cmpStaff.IngestRecord(
    {
        Name: txtName.Text,
        Role: txtRole.Text,
        Photo: AddMediaButton1.Media
    }
)

And the results:

No alt text provided for this image

Oh, and don't forget, action properties give an output too 😁

If(cmpStaff.IngestRecord(
    {
        Name: txtName.Text,
        Role: txtRole.Text,
        Photo: AddMediaButton1.Media
    }
),Notify("Record added"))

Next Time

We'll take a look at Events, which are probably already familiar to those who used Behaviour properties in the past.


Thanks for reading this article, I'm wondering, what are your use cases for Actions? I'd love to read them in the comments below 👇