Components - Let's Make a Function!⚙

Components - Let's Make a Function!⚙

Photo by Anton Mislawsky: https://www.pexels.com/photo/close-up-of-machine-part-246753/

Continuing with this series on Components and Component Libraries, this article will go over how to write re-usable functions using one of the new Behavior properties of components.

Anyone familiar with any scripting/programming language will have more than likely come across a function before. If you haven't though, that's okay!


What is a function?

A function is a reusable piece of code. we don't like to repeat ourselves, so if we're in a situation where a block of code may be needed more than once, a function might be the answer!

A function will typically takes 0 or more parameters and will usually (but not always!) return data as a particular data type. An example of a function in PowerShell would be:

function addcat ($inputString, $cattiness)
{
    $cat = "🐈" * $cattiness;
    return $inputString + $cat
}

This function has a super important business function of adding n cats to the end of $inputString. Now that this is a function declared in my veryImportantForTheBusinessScript.ps1 file, I don't need to retype this the 25 times I have to call this code, I can simply, instead, do:

addcat -inputString "Classified" -cattiness 7

and the function will return the string required.

No alt text provided for this image

In some ways, they're like printers that actually work. You pass your parameters (Print Data, Paper, Toner) and the printer will return a printed document, sometimes. But our functions are more reliable than printers.

The benefits of functions are:

  • Reusability ♻️ Write Once, Deploy Many, or as Craig White puts it: Don't be WET [Write Everything Twice]

  • Code Simplification 🦀 Now you don't need to repeat your code, your code will become easier to maintain and read. You can even reduce nested conditions!

  • Increase maintainability 🔨 Function not working? At least you can now fix that bug in one place, not every instance where you wrote that code block!


So how do I make a function in a Canvas App/Custom Page? 🤔

Whether you're building out your component library to help support your maker community, or you're making a component within a Canvas App; you'll first want to ensure you have "Enhanced component properties" from "Settings" > "Upcoming features". This will enable the ability to add Functions to a component.

No alt text provided for this image

⚠️ BUT TAKE HEED! ☝️

This is an "Experimental feature". That means this feature is earmarked as one that could change; or worse, disappear in the future, so implement at your own risk!

Enabling this option should now give you additional property types when adding new properties to your components 👇:

No alt text provided for this image

The old options

No alt text provided for this image

New options, with additional property types


But what do these "Property types" mean? 🙋

  • Data: Your standard component property, can be defined as an "Input" or an "Output" and it's data type defined as well, (Text, Number, Record, Table etc). These allow you to bring properties into your component, so for example, you could define a font size, or alternatively return values from your component, like text entered into a text box.

  • Function: The focus of this article, this is a property that can be "called" from your app, providing the component is present. Functions cannot access the App or Component variable scope.

  • Event: This replaced the previous "Behavior" property type. Events can be triggered from within the component, but handled on the App side. In essence, you can map an event like OnSelect(), OnChange(), OnChecked() etc to a property, for your app to then handle. This can be used to; for example, write a patch function in the app into the component.

  • Action: Action properties are similar to Function properties but have scope within the component itself. Actions are super interesting, and there'll be a beefy article coming soon🐄!


So, let's make a function! 🔨

Let's use the cat example from my PowerShell example earlier.

We'll start by creating a Function Output custom property

Add this to your component and name it "Add Cat"

No alt text provided for this image

We then need to add two parameters:

  • InputString | Text | This is the text we wish to manipulate | Required

  • Cattiness | Number | How many cats! | Optional

Those parameters can be used when calling the function to influence the function, as per the code we'll write shortly.

The next task is to write the logic for our function ✏️

You can now select the "Add Cat" custom property, or find it in the property drop down [Top Left!]

No alt text provided for this image

Note how our parameters are displayed here, we can open each parameter and manipulate it's default value. This is really important when we work with records or tables as we'd need to define the default schema of these. For now we can keep Cattiness and InputString as 100 and "Text" respectfully.

Select "AddCat" and enter the following formula:

With(
    {
        cats: ForAll( //For x Cattiness, add a cat
                Sequence(
                    Cattiness),
                    "🐈")
    },
    $"{InputString} {Concat(cats,Value)}") //Concat and return string

☝️ This mimics what I did in PowerShell by adding x cats to the end of "InputString". The last line sets AddCat to the string value to return to the app.

That's it! Let's get testing!


Go ahead and add the component into an app, along with two text boxes and a slider for good measure.

No alt text provided for this image

Well, it's not exactly Kristine Kolodziejski level UX material, but it'll do for now!

In the example above, we're using a text box to capture our InputString, a slider to capture the cattiness of it all 😸 and a third text box with DisplayMode = "view" to display the result of our function.

Now set the output text box to the following code, replacing component names accordingly:

cmp_Demo.AddCat(txtInputString.Text, sld_Cats.Value)
//cmp_Demo = our component

And, viola! You've created a reusable function!

Easy! Right? And here's some tips to take away:

  • Functions will work if your component is invisible. So go ahead and set that functions-only component's visibility to a big fat !true

  • But consider reducing your component 👣 You could try adding functions in commonly used components.

  • Make sure your makers know the functions are there! 👀 Use my previous tip of including a "Readme" input property to help unearth your shiny functions!

  • You cannot access the components Variables or Input/Output values in a Function. These are completely independent code blocks in your components and rely on Input Parameters.

  • We just wrote an output function, but you can also write input functions as well! So you can offer the ability to write functions from the app INTO the component. But I'm not 100% why... 🤯

Thanks for reading! Next time...

We're going to crack Actions and see how they differ to functions. 🦀