# Custom Functions In Flows

Imagine you want to run some javascript on some event in North Commerce. For example, if you want to track add to cart events with a 3rd party analytrics tool you could add a javascript function to run when a website visitor clicks "Add To Cart"

## Add To Cart innerText Example

North Commerce has a “flow” system that dynamically reads and writes data onto HTML elements via attributes. It also supports “linking” an attribute to a custom JavaScript function. Whenever the flow engine reads or writes a value for that attribute, your JS function is called.

**Attributes** in flows hold data such as `event`, `trigger`, or `executing`

**Linking** an attribute to a function allows custom behavior. For example:

* Setting a button to “disabled” when a flow is running (e.g., while adding to cart).
* Changing the button text to “Loading…” in the meantime.
* Sending analytics calls whenever a user clicks “Add to cart.”

In my regular HTML markup I have my button that I want a user to click to add an product to their cart.&#x20;

In my PHP file I will import the Cart\_Quantity\_Flow and create a new isntance of it.&#x20;

```php
use NorthCommerce\Ui\Flows\Cart_Quantity_Flow;

$quantity_flow = Cart_Quantity_Flow::instance();
```

<pre class="language-html"><code class="lang-html"><strong>&#x3C;button> Add To Cart &#x3C;/button>
</strong></code></pre>

We use standard html and then we can add our flows to get it to add to cart&#x20;

```php
 <button
    class="nc-cart-btn"
        <?php $quantity_flow->attr('trigger', 'plus-n') ?>
	<?php $quantity_flow->attr('event', 'click') ?>
	<?php $quantity_flow->attr('product-variant-id', '', '.product-container') ?>
	<?php $quantity_flow->attr('quantity', '', '.qty-input:value') ?>
  >
        Add To Cart
        </button>
```

Now I want to add functionality to disable the button and update the innerText when a user clicks the Add To Cart button. In order to do that I need to add a few things.&#x20;

```php
 <button
    class="nc-cart-btn"
        <?php $quantity_flow->attr('trigger', 'plus-n') ?>
	<?php $quantity_flow->attr('event', 'click') ?>
	<?php $quantity_flow->attr('product-variant-id', '', '.product-container') ?>
	<?php $quantity_flow->attr('quantity', '', '.qty-input:value') ?>
        <?php $quantity_flow->attr('executing-class', 'nc-disabled-btn') ?>
        <?php $quantity_flow->attr(
                'executing-text',
                esc_attr__('Loading...', 'north-commerce')
            ); ?>
            <?php $quantity_flow->attr('executing', '', 'fn.Nc.Ui.showLoading') ?>
           
        >
	
        Add To Cart
        </button>
```

I added a few new attributes from the quantity flow here. I have added an nc-disabled-btn class when the button is in the "executing state"

I set a custom attribute called `executing-text` . In our flow system you can add any number of attributes that you can then access or select in your functions

and lastly I have added this function in the `executing` flow attribute.

```php
<?php $quantity_flow->attr('executing', '', 'fn.Nc.Ui.showLoading') ?>
```

Inside of flow attr you need to declare where you want this function to run, in this case its when we executing state is true.&#x20;

Then we call the function with the prefix `fn`. In this example we are using our namespaced showLoading function. You can leverage built in North Commerce flow utility functions like this or you can write your own inline javascript to call.&#x20;

Inside of the showLoading() function 3 arguments are automatically passed into it.&#x20;

Attribute Name - attrname\
Flow Context - fc\
value

```
showLoading(attrName, fc, value) {
  ....
}
```

## Flow Context

I will focus on Flow Context and Value. These are the most common values you will be using when using flows in Javascript.&#x20;

Flow Context (fc) gives you access to everything on that element including the element itself.&#x20;

```javascript
showLoading(attrName, fc, value) {
   const executingText = fc.getAttr('executing-text');
   const executingClass = fc.getAttr('executing-class');
}
```

You can get the values from the attributes you set in your php file with flows. So the code `const executingText = fc.getAttr('executing-text');`  is getting the text we set of **Loading...**

You can also get the element  with flow context with `fc.elt()` So lets say we need to get the innerText or innerHTML of the element before it was set to loading so we can revert the text back to its original state when the add to cart has been finished. You can do this:

```javascript
fc.elt().innerHTML;
```

You can also add new values to the flow context object like we do here

```javascript
 fc.beforeLoadingInnerHTML = fc.elt().innerHTML;
```

## Value

Value is a boolean. This will return true or false based on if in this case `executing` is true or false

### Complete Show Loading Function

```javascript
 showLoading(attrName, fc, value) {
            if (value !== undefined) {
                const executingText = fc.getAttr('executing-text');
                const executingClass = fc.getAttr('executing-class');

                if (value === true) {
                    if (executingText) {
                        // Use a property to store the original innerHTML
                        fc.beforeLoadingInnerHTML = fc.elt().innerHTML;
                        fc.elt().innerHTML = executingText;
                    }

                    if (executingClass) {
                        fc.elt().classList.add(executingClass);
                    }
                } else {
                    if (executingText) {
                        fc.elt().innerHTML = fc.beforeLoadingInnerHTML;
                    }

                    if (executingClass) {
                        fc.elt().classList.remove(executingClass);
                    }
                }
            }
        }
```
