# Components - Let's Make a Function!⚙

[**Continuing with this series on Components and Component Libraries**](https://sgtcrab64.hashnode.dev/component-libraries-lego-blocking-canvas-apps)**, 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:

```plaintext
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:

```plaintext
addcat -inputString "Classified" -cattiness 7
```

and the function will return the string required.

![No alt text provided for this image](https://media.licdn.com/dms/image/D4E12AQGVXubiaBHRfw/article-inline_image-shrink_1500_2232/0/1687468305069?e=1700092800&v=beta&t=oJI_zbwOiAMYEGboeUWAKb7F82h8CK4OpmrGODtPVGg align="left")

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](https://www.linkedin.com/in/craig-white-?miniProfileUrn=urn%3Ali%3Afs_miniProfile%3AACoAADJn4_QBlGurocOqEq6Qw6OE4FboAzJoIMk) 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" &gt; "Upcoming features". This will enable the ability to add Functions to a component.

![No alt text provided for this image](https://media.licdn.com/dms/image/D4E12AQEfDypWOAqxdQ/article-inline_image-shrink_1500_2232/0/1687468518171?e=1700092800&v=beta&t=LLwDbfiDhcP-D5CNJR63ITHERxGYDKv-AMCSwQD-Z-U align="left")

> ⚠️ 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](https://media.licdn.com/dms/image/D4E12AQEyBAPpiCBVOg/article-inline_image-shrink_1500_2232/0/1687468988546?e=1700092800&v=beta&t=db0nTNPQBO3_SuDm5gc7u2n74rMAeAKqI9BiRucYMHM align="left")

The old options

![No alt text provided for this image](https://media.licdn.com/dms/image/D4E12AQEEU4HEKRzWiQ/article-inline_image-shrink_1500_2232/0/1687469002806?e=1700092800&v=beta&t=OZoYT7iO07sIo_0EKZ99gSZlPNyw25hUlIyRm-CwDoM align="left")

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](https://media.licdn.com/dms/image/D4E12AQE2XMpOq77blw/article-inline_image-shrink_1500_2232/0/1687470781582?e=1700092800&v=beta&t=1edEPO8yCPlO78bcIz7fowGQ5TnBsPl3dizRaDJGuBk align="left")

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](https://media.licdn.com/dms/image/D4E12AQHg60-IX6iJTg/article-inline_image-shrink_1500_2232/0/1687471179708?e=1700092800&v=beta&t=DK5NQaYzowkGqfe8yQF1QfgGvjsE4fGQ99x2hmiFIJ0 align="left")

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:

```plaintext
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](https://media.licdn.com/dms/image/D4E12AQH_lC9YbKrhTQ/article-inline_image-shrink_1000_1488/0/1687471849374?e=1700092800&v=beta&t=RAMa6Rcu2ObSpll3T7WoKp8y6q2bUMILyrbl4HLIm_8 align="left")

*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:

```plaintext
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. 🦀
