Custom Functions In Flows

With Flows you can run custom javascript functions to provide custom functionality.

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.

In my PHP file I will import the Cart_Quantity_Flow and create a new isntance of it.

use NorthCommerce\Ui\Flows\Cart_Quantity_Flow;

$quantity_flow = Cart_Quantity_Flow::instance();
<button> Add To Cart </button>

We use standard html and then we can add our flows to get it to add to cart

 <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.

 <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 $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.

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.

Inside of the showLoading() function 3 arguments are automatically passed into it.

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.

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

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:

fc.elt().innerHTML;

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

 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

 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);
                    }
                }
            }
        }

Last updated

Was this helpful?