The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
DirkRedeker
Mega Sage

Hi everybody

Welcome to my third article about the NOW UI Experience Component Development

 

A few questions to you upfront:

  • Are you keen on learning to develop NOW UI Experience Components?
  • Do you have a basic understanding of creating NOW UI Experience Components?
  • Did you read my previous articles (as a baseline for this one) before?
  • Are you interested in learning details of NOW UI Component Event Handling?
  • Are you a developer?
  • Do you have a dog?

If you scored once, you may be right here.

If you scored twice, you should read this article.

If you scored more than two times, this article is a MUST for you.

 

Note:
If you are NO developer, maybe you should close this article right now - this may be off-topic for you.

 

 

If you are new to the development of NOW UI Experience Components, just follow the link below to get a jump start on this new technology (the link navigates you to my first article about NOW UI Experience Components):

Fast Track to your first "Now Experience UI Framework Component

If you are not familiar with Properties in NOW UI Experience Components, you may want to read the second article I wrote on that topic (which may be handy to understand the topics covered within this article. You can find my second article (about the Properties) by following the link below:

Now UI Experience Part #2 - Workshop: Using multiple Component nesting & Parameter passing

 

This article was written in October 2020. So, your future self may indicate, that this content may NOT be correct "anymore", but for now: "Back to the future".

 

Today's topic

In this article here, you can learn about the Event Handling in NOW UI Experience Components. In ServiceNow wording, we will talk about "Action" that is being "dispatched" (like the Events that are fired) and "Action Handlers" (like Event Handlers) that will be triggered by the Actions (Events).

If you followed my previous article about Properties (link see above), you know the principle, that properties "drop down" in the component hierarchy and now you will learn, that Events (the "Actions" in ServiceNow terms) bubble up.

If you understand these two very basic principles, you can play with the components and their structure and relations very smoothly afterwards.

 

Scenario

As also the previous article, you will not get a full-blown NOW UI Component by following this article, but you will learn about the concepts needed for driving YOUR OWN ideas into reality!

You will learn :

  • about "Actions" and "Action Handlers" and what they are
  • how Components can interact from one component to another
  • on how to set them up in your NOW UI Components projects
  • how to dispatch (fire) Actions (Events) and how to react/trigger on them

What you cannot learn from THIS article - which is too large to also cover in this article - is:

  • Actions to interact with the ServiceNow database using HTTP calls. This will be the topic of the next article, that I am planning to release on the NOW UI Experience Component development.
  • Where I have hidden the treasure
  • Why 42 answers everything!

 

Environment

I am doing this development on a Windows 10 Box. The steps to follow for MAC would be quite similar.

The ServiceNow version that I am using is the PARIS Release on a Personal Developer Instance (PDI).

Check the version of your instance by typing "stats.do" in the Application Navigator and hit <Enter>

image

I am using the following tools and versions

  • now-cli in version 18.0.0 (note, that Version 18.0 currently only supports PARIS and NOT Orlando)
  • npm version 6.14.6
  • nodejs version 12.18.3
  • VS Code for development (any current version will be fine)

 

Note:

  • Use the "now-cli" version 18 on PARIS Release ("npm install @servicenow/cli@paris -g")
  • Use the "now-cli" version 17 on the ORLANDO Relase ("npm install @servicenow/cli@orlando -g")

 

Are you ready for Action and Handling Actions?

If YES, move on to Step 1
If NOT, wait and come back later..........

 

 

Step 1 - Some concepts first, to warm up!

Don't waste time - let's go

The diagram below shows an example of three components, which are used in a nested way to each other.

Outmost, you can see the blue "Main Component", which uses the green "Table Component" as a sub-/child-component. And the green "Table Component" in turn, uses the red "HTML Link/Anchor Component" as a child-component.

find_real_file.png

You can see, that the blue "Main Component" can "drop-down" (1) Properties (of literals types or even complex object types) to the green "Table Component". The green "Table Component" then can use values to "drop-down" (2) Properties to the red "HTML Link/Anchor Component".

Note:
The blue "Main Component" in this scenario can NOT (3) directly pass (drop down) values down to the red "HTML Link/Anchor Component", because the red "HTML Link/Anchor Component" is NO direct child of it. Each Component can only drop-down Properties to its own children!

Note:
Properties are "ONE-WAY", which means, that the only can be passed from the PARENT to the CHILD Component(s), but NEVER the other way round (from the CHILD(REN) to the PARENT).

So far so good! That should have been clear from my previous article.

 

Now, let's make the scenario a bit more complex (which will occur one day, when your NOW UI Components Projects grows up).

The diagram below shows the scenario extended by another green "Table Component", which was used by the blue "Main Component". this means, that both green "Table Components" are "siblings" (and on the same hierarchy of nesting). Both green "Table Components" do have the same blue "Main Component" as a parent!

Note:
Take care, that both red "HTML Link/Anchor Components" are NO direct siblings anymore. They are on the same nesting level of the component structure tree, but their PARENTs are different ones.

What you can see in the diagram below is, that events (the ServiceNow "Actions") that are dispatched (fired) within the red "HTML Anchor Component" can trigger "Action Handlers" (event handlers) in its own (4) instance of the component, but also can trigger the corresponding "Action Handler" UP in their nesting hierarchy. So, the Action dispatched in the red "HTML Link/Anchor Component" (5) can trigger an Action Handler in the green "Table Component" (which is the parent).

One very important thing to know is, that the event will even "bubble" higher in the component nesting hierarchy so that even the blue "Main Component" can trigger the Action Handler, (6) based on the Action dispatched in the red "HTML Link/Anchor Component". We will learn all these scenarios below. Stay tuned!

find_real_file.png

As described for the Properties, which only can "drop down" in the Components' nesting hierarchy (and not "drop upwards" - makes sense :-)), Actions dispatched (Events fired) can only bubble up in the Components' hierarchy (on not "bubble down"!!!).

Keeping that said in mind, it should be clear, that "siblings" (the both green "Table Components") cannot talk to "each other" (9), because Actions only bubbles up to their PARENT Component.

Even more obvious is the fact, that the both red "HTML Link/Anchor Components" CANNOT "talk" to each other - not by Actions dispatched, and also not by Properties to be dropped in! In NO direction.

Note:
As you can find in the diagram above, you can stop events to bubble up further (8) in the component nesting hierarchy (called "STOP PROPAGATION"). That way, you can trigger the Event Handler in the green "Table Component", but from there, you could prevent to trigger the corresponding Action Handler in the blue "Main Component".

 

If you want to have Components "talk" to each other, the always needs to "talk" (by dispatching Actions) UP in the hierarchy, just to where you can find the path back down to the "other" component!

The diagram below shows the left red "HTML Link/Anchor Component", which wants to send some information to the right red "HTML Link/Anchor Component". This is NOT possible in the direct way as indicated with the dotted line (1).

find_real_file.png

In spite of using the (impossible) direct path (1), you need to dispatch an Action from the red "HTML Link/Anchor Component", which in turn can trigger an Action Handler (2) in the blue "Main Component".

The blue "Main Component" then can "do something" (3) with the Action data (the action payload information) and drop down the data (4) using the Properties of the right green "Table Component". Because the blue "Main Component" cannot directly pass values down to the right red "HTML Link/Anchor Component", the right green "Table Component" must "forward" (5) the data from the blue "Main Component" down to the right red "HTML Link/Anchor Component".

 

OK!

Take a minute and take a deep breath! This must be (or become) a very clear basic principle when developing NOW UI Components! You will need that later to "architect" your components in a nice and reusable fashion.

 

 

 

Step 2 - Create a new NOW UI Component Project

We want to start with a blank and empty project. To set up the environment to follow the article, just...

Follow the steps below (I name my Project "Article13"):

  • Create a NEW and EMPTY folder on your local drive (NOT any cloud drive attached folder!!!)
  • open your command prompt and change to that directory
  • make sure, that you have a matching "now-cli" version, that matches your instance Release
    ("now-cli" version 18 for PARIS Release; and "now-cli" version 17 for ORLANDO Release)
  • make sure to have "npm" and "nodejs" installed in some current versions
  • connect to your ServiceNow Instance with the "now-cli login" command
  • create the scaffolding project with the "now-cli project" command
  • load the project dependencies with "npm install"
  • open your project folder in the editor of your choice (I use VS Code)
  • write some "Hello World" into the Component, that was "Scaffolded" for you
  • run and test your component project with "now-cli develop --open"

Note::
You can find step-by-step detailed instructions on my both previous articles about NOW UI Component development at the top of this article.

Review the screenshots below for reference on the steps taken....

find_real_file.png

find_real_file.pngfind_real_file.png

find_real_file.png

find_real_file.png

find_real_file.png

Here we go! Ready to concentrate on ACTION!!!

 

 

 

Step 3 - Create a simple button with Event-Handler

In this step, we will add a simple HTML button to the "view" function of the NOW UI Component. This button will have an Event Handler, that just writes some text to the Browser Console.

In the "index.js" file (see screenshot below), just below your "Hello World..." text (in line 8), add a "<p>" and closing "</p>" Tag (Line 9 and 15). Inside of this tag, add a "<button></button>" (1) element, which gets some parameters (line 11 to 13).

The important part here is line 12. This wires up a function call to the "on-click" event (2) of the button, which means, that the given Arrow function "() => {}" (3) will be executed as soon as the button is pressed.

The Arrow function just executes a "console.log()" command to write the current date/time to the console output window of the web browser.

find_real_file.png

 

The screenshot below shows the component in action:

To open the Web Browser Console, just press the "<F12>" key. As I am using the Chrome Web Browser, I just need to click on the "Console" tab to show the Console output, which gets cleared at each page reload automatically.

The Warnings (in yellow) and Errors (in red), which are now already shown, can be ignored for now and you can click on the small circle icon in the Console window, to clear the current output of the Console log.

find_real_file.png

 

After clearing the console log, click on the button (1) of your brand-new component, to get YOUR current date/time in the Console output.

find_real_file.png

Challenge:
Try to figure out, why your output may certainly be different to (2) mine (shown in the screenshot) 🙂
You are welcome to write the reasons you figured out for this in the comments below in this article.

find_real_file.png

Nice!

Now, we converted the static NOW UI Component to be dynamic. Remember, that the components will remain static until you implement Actions and Action Handlers.

All right! This is not really THAT much specific to NOW UI Components. Let's get a bit closer to that target in the next step!

 

 

 

Step 4 - Create an Action Handler and dispatch an event

In this step, we will add an Action Handler to the ComponentConfig Object of the NOW UI Component to trigger on the click of the button. We change the button to dispatch an Action itself.

Let's refactor the example from above, so that the event function "on-click()" of the button "dispatches" an "Action", which in turn will trigger an "Action Handler". The resulting outcome will be the same, except that we introduced the basic concept of Actions and Action Handlers.

Take the following refactor-steps (review the result in the screenshot below):

a) To create the function that triggers (the "Action Handler")

  • create the "actionHandlers" element (1) in the "ComponentConfig" Object (line 25)
  • Add the Action Handler (line 26 to 29) - take care of all the braces and commas etc.!
  • I named the Action Handler 'DIRK_HTML_BUTTON_CLICKED' (2) as a static literal (line 26).
    It is best practice to define a "const" for the name of the Action Handler and use this in all places
    It is also best practice to find a naming schema for your Action Handlers and make sure they are UNIQUE. Best to add some company/project/whatever specific prefix to the Action Handler name.
    It is not necessary, but best practice to write the Action Handler names all UPPER_CASE
  • move your "console.log()" command inside the function definition (3) of the Action Handler (line 27)

b) To dispatch the Action that will trigger the newly created Action Handler

  • change the "on-click" event handler of the button to execute the "dispatch()" function (4)
  • As the first parameter of the "dispatch()" function, fill in the name (as string) of the Action to "fire"(5)
  • The "dispatch()" function must be made available for the "view()" function (6) by de-constructing the helpers parameter (the second parameter passed in to the "view()" function (in line 5).
    The second parameter "{dispatch, updateState}" is just an "in-line" deconstruction of the helpers!

find_real_file.png

Save these changes and try the outcome in your web browser. The result must be exactly the same as before (except that - depending on the speed of light - the time may have changed meanwhile)!

find_real_file.png

 

Key finding #1 - dispatch Actions:

You need to leverage the "dispatch()" function to "fire" NOW UI Component" Actions. The "dispatch()" function is made available to the "view" using the second parameter of the view function (as part of the helper object).

The first (and mandatory) Parameter of the "dispatch()" function is just the name of the Action to fire/dispatch. Make sure, that the code running has currently access to the "dispatch()" function, which is the case inside of the "view()" function.

Note:
Review the screenshot below for the short form of de-constructing the "helpers" in the second parameter of the view function. It can also be coded in two steps. This time, you pass in (1) all the "helpers" (line 5) and do the de-construction (2) on a separate code line (line 7).

find_real_file.png

 

Key finding #2 - consuming Actions with Action Handlers:

To trigger Actions using Action Handlers, the Action Handler must be "registered" in the "ComponentConfig" object of the "createCustomComponent" function call (see screenshot below).

Have a closer look at the function call of "createCustomElement()" in line 24. If you follow up the opening (1) in line 24 and closing parenthesis (2) in line 33, you will see, that the "createCustomElement()" function has TWO parameters, which in fact are:

  • the name of the Component
  • an object variable of type "ComponentConfig", which holds several elements (like "view", "renderer", "styles" and also the "actionHandlers")

find_real_file.png

 

Challenge: (works for VS Code)
If you like deep-diving, as I do, you can mark the function call to "createCustomElement" and right-click on the call, and select "Go to Definition" (see screenshot below). Alternatively, you can mark the function name and press <F12>, which also navigates you to the definition.

find_real_file.png

The screenshot below shows the definition of the "createCustomElement" function, which sits deep in one of the source-code files of the NOW UI Component Framework files. Those files are installed in your project directory when you called "npm install" - at the very beginning of this project.

find_real_file.png

The top header line of the window (1) shows the path to the definition file, which is located in the "node_modules" folder of your Component Project. The folder "@servicenow" has a subfolder "ui-core", which in turn has a "typings" folder! Finally, there you can find the "index.d.ts" script with the function definition.

The function declaration of the "createCustomeElement()" function (2) has two parameters. The first parameter is the Elementname (3) and the second parameter is called "config" and is of type "ComponentConfig".

What "ComponentConfig" contains in detail (5), is defined in the same code file starting in line 6. Here you can find the definition of the "actionHandlers" element of the ComponentConfig object (in line 16).

We will get back to more of the "actionHandler" element details one-by-one later.

Great!

Now, we can already make our Components quite interactive! We can add as many HTML UI elements as needed, where each of them may dispatch its own Action and this will trigger individual Action Handlers.

But what we currently did, was only showing some output in the Browser Console output, and did not change any content shown in the browser window. So, the "view()" function output was not affected yet by the Action Handlers that we have implemented.

 

Let's move on to the next step to explore on how to update the visual representation of your NOW UI Component at Run-Time.

 

 

 

Step 5 - The Component's "state" object

In this step, we will review the Component's "state" object and its "initialState" object definition inside of the ComponentConfig object.

 

The Component's State

Each time you instantiate a component, it creates a separate "object" for that specific component instance in memory. For each component to "remember" it's local values (and variables), the "state" object exists and lives inside each NOW UI Component.

Because the "state" is of type Object, it can contain any number and any type of elements and data inside. You do not need to create the "state" object on your own. It is created automatically for you and is passed into the "view()" function (1) as the first parameter (see line 5 in the screenshot below).

find_real_file.png

You can easily access the content of the "state" object (3) from inside your "view()" function with the syntax shown in line 20 and 22 in the screenshot above.

 

The initialState object

To initialize the state with some values when the component instance object is created, use the "initialState" element (2) of the ComponentConfig object (described above). You can find an example in line 30 to line 33 in the screenshot above. The element "initialState" just defines an object with the elements to store in your specific "state".

Save the changes and review the results:

find_real_file.png

Note:
The "state" object is no "global" object to your component, which means, that it is not available everywhere in every function of your component. It must be passed into that function, which is done automatically for you to the "view()" function - but also to all Action Handlers (we will discover soon).

 

Challenge:
If you are a deep-diver and want to review the contents of the "state" object variable, you can easily dump it to your browser's console log window, by using the following line shown in the screenshot below:

find_real_file.png

Remember "JSON.stringify()", which formats any JavaScript Object to a String output. Using the second (null) and third parameter (4), you can beautify the output to a nice human-readable format.

The console output will look like shown in the screenshot below. You can find the two elements of the "state" that have been set up with the "initialState" object definition.

find_real_file.png

 

 

 

Step 6 - The "coeffects" Parameter of Action Handlers

In the examples above, the Action Handler we created had NO parameter passed in. But this is just an option. You can pass in an optional object which is called "coeffects" in the documentation. This coeffects object contains the "state" as an element (a copy of the state object). Knowing this, you can access the values of the "state" object inside your Action Handlers as well.

Review the code changes done in the screenshot below to see how the coeffects are leveraged inside of Action Handlers.

find_real_file.png

Add the parameter named "coeffects" into the parenthesis for the Action Handler (1). This automatically passes in the "coeffects" object to your Action Handler.

In code line 41, you can see how to update an element of the state (copy) "manually" by assigning a value directly to an element of the state object inside "coeffects". Line 42 shows how you can dump the whole "coeffects" object to your browser console in a beautified human-readable layout (using "JSON.stringify()").

Thanks to @Chuck Tomasi for repeating this nice command in several of his great videos on YouTube. This comes in very handy here.

 

Note:
Updating the "state" as shown above may NOT be your best friend, and we will see in which cases you will not be satisfied to assign values in that way to your "state" object.

The output in the Web Browser console output, after clicking the button of your NOW UI Component, is like shown in the next screenshot:

find_real_file.png

The "state" object is marked in the upper red box and you can see, that the "clickedLast" element of the "state" has been successfully updated by the value assignment ("clickedLast" is now set to "in ActionHandler". Initially, it was set to "at no time" by the "initialState" object definition).

The "action" object is marked in the lower red box and this reflects the Action triggered (in the element "type:" set to "DIRKS_HTML_BUTTON_CLICKED").

 

Challenge:
Who can tell me what the yellow marked string in the screenshot will mean? Any advice is very welcome down in the comments. I am also looking forward to your funky ideas about the meaning of this term. Just write down what you think about it - have fun!

 

Now having the "coeffects" object in your Action Handler, there are also two functions made accessible via the "coeffects" object. These are "dispatch" and "updateState".

The function "dispatch" again allows dispatching further Actions from inside your Action Handler itself. This way, you can cascade your Action Handlers in any needed sequence. See the screenshot below for an example of how to dispatch another Action from within an Action Handler (on line 44).

find_real_file.png

The "coeffects" object contains the "dispatch()" function which fires another Action. This Action is triggering the Action Handler defined on line 47. This in turn just prints one line to the web browser console log output. Review the screenshot below for the new output in the web browser console AFTER those changes.

find_real_file.png

The upper red box output (1) is from the FIRST Action Handler and the lower red box output (2) is from the new cascaded Action Handler.

Cool thing - indeed!

 

The details and usage of the "updateState()" function (passed into the Action Handler with the "coeffects" object) is described in the next step below.

 

 

 

 

Step 7 - Changes to the "state" object and the "updateState()" function

Changing / Updating the Component's State

Like we reviewed above, you can access the elements of the "state" object in the "view()" function of your NOW UI Experience Component with the syntax "state.elementname" and you even can change the values of the state's elements with that syntax.

But if you have taken a closer look and took attention to what happened above when we changed the "state" element values, you will find out, that the values of the "state" elements have been (obviously) changed successfully, but their values have NOT been reflected in the visual representation of the component.

find_real_file.png

Review the notes on the screenshot above in detail to understand the current situation. The resulting issue is, that changes of the "state" elements are not updated in the Web Browser showing the Component!

 

Using "updateState"

Instead of assigning values directly to "state" elements (with "state.element = value;"), you can use the "updateState()" function. This function is available in Action Handlers via the "coeffects" object (see above) and can be used to set new values to the elements of the "state" object AND to automatically update their representation in the web browser window.

The "updateState()" function is also accessible inside the Component's "view()" function, and comes in as part of the "helpers" (the second parameter of the "view()" function. If you view function is declared as:

const view = (state, {updateState}) => {...}

you will have direct access to the "updateState()" function inside the "view()" function. If you review,the de-construction of the helpers, you know how to get the path to use it. Play around and figure out!

 

Note:
As far as I understand the whole game, the "updateState()" function will result in updating the Virtual DOM of the current NOW UI Experience Component in the background, and this in turn will update the HTML in the web browser.

 

The general syntax of the function is "updateState( {stateelements} )", where "{stateelements} represents any number of element names and values to be set in the "state" object.

The screenshot below shows an example of using the „updateState()“ function within an Action Handler. You can see that the "updateState()" function is called as a member of the „coeffects“ object (which is passed into the Action Handler as a parameter in line 38).

The “updateState()” function gets one parameter passed into the function call, which is an object holding “state” elements to be set or updated. This object is similar to the object set to the “initialState” object element of the ComponentConfig object (we reviewed above).

In the example, I set the value of the “state” element called “clickCounter” to the value found in the same element of the state element "clickCounter" currently PLUS ONE (“+ 1”). This just increments the value of the number of Clicks. But this time, this element is intended to be updated in the web browser window as well.

find_real_file.png

The resulting output in the web browser after clicking the button looks like shown in the screenshot below. Also this time, the Component's state object (not just the copy one of the "coeffects") is permanently updated to the new value.

find_real_file.png

The “clickCounter” element (1) was set with the “updateState()” function from the initial value “0” to “1”. These values is available in the new “state” element passed into the “view()” function and will be reflected accordingly in the web browser window (3).

The “clickedLast” element (2) was NOT set using the “updateState()” function, but was only set as an assignment to the element of the state passed into the Action Handler via the “coeffects”. This change (from “at no time” to “in ActionHandler”) was NOT stored in the Component’s “state” object. This results in showing the old value in the web browser. In fact, the change to the “state” element “clickedLast” was lost.

Take a minute to review in detail what happened here. It will be worth it, to understand the bits and pieces!

 

Findings

You can “play” around with the “state” element by assigning values to the “state”, but until you really update the “state” elements using the “updateState()” function, the changes will be lost, the next time the “state” object is passed into your “view()” function.

You now know how to access the “state” object and update the state values of the Component. Keep in mind, that each instance of the component has it’s OWN “state” object, and no one Component can directly access the content of the “state” object of another Component. They are separated and isolated.

You also know that the “updateState()” function calls the “view()” function again to reflect the current values of the “state” object in the output to refresh the web browser window.

You learned, that you just need to add the “coeffects” parameter to your Action Handler and you are ready to use it inside your Action Handler (by the way: you can name it whatever you want – “coeffects” is just found in the documentation).

You learned that the “coeffects” object contains (a copy!?!) of the “state” passed into the Action Handler.

You learned that “dispatch()” and “updateState()” are functions of the “coeffects” object passed into the Action Handler, so you need to add the “coeffects” parameter to your Action Handler to access these both functions from within your Action Handler code.

 

 

 

Step 8 - Function "updateProperties()" vs "updateState()"

In addtions to the "updateState()" function comes the "updateProperties()" functioin with the "helpers" injected into the "view()" function, or with the"coeffects" injected into the Action Handlers.

As you learned in my previous article, a Component has Properties, that can be passed in using the JSX properties or HTML attributes, just like

<x-269923-zview
    dbTableName='incident'
    myStateDataset={state.myStateDataset}
></x-269923-zview>

These properties are directly passed into the "Properties" object of the Component and can be consumed from the state inside the "view()" and Action Handlers as part of the "coeffects" object injected to the Action Handler.

Please make sure, that the "Properties" and the "State" are different!

There is a separate helper function called "updateProperties()", which is used to change values in the "Properties" element of the Component's data. Its usage is very similar to the "updateState()" function - review in the screenshot below.

find_real_file.png

The Property "internalProp1" (1) defined in line 43 gets an initial value (default) of "some String", which is shown in the Components view (3) in line 18. As soon as the Action Handler "DIRKS_HTML_BUTTON_CLICKED" is triggered (in line 49), the "updateProperties()" (2) function in line 52 is executed to change the given element value of the Component's Properties (property called "internalProp1").

The changes affect the execution of the view() function and reflect the change in the Component in the web browser immediately.

 

 

 

Step 9 - Dispatch Actions with "payload" data

In the previous exercises and steps, we first triggered the Action Handler by passing in the “Action Name” as the first parameter to the “dispatch()” function. Then, we found out, that the Action Handler function accepts one object parameter (the “coeffects”), which contains the “state” data and the “helper” functions (“dispatch()” and “updateState()”).

But what, if we want to pass some data WITH the event?

Remember from the diagrams above (at the beginning of this Article): We can only communicate with parent components via Actions (events) that “bubbles up”. Maybe we want to pass (communicate) some data with the Action to the Action Handler (no matter if we want to pass data to an Action Handler within the same Component OR whether we want to pass some data to an Action Handler in the nesting hierarchy upwards).

 

Adding data to the dispatched Action

To add data (as a JavaScript object) to the dispatched Action, we just need to pass in an object as the second parameter to the “dispatch()” function call, which may then look like:

dispatch(‘NAME_OF_THE_ACTION’, {});

where “{}” represents the object to be passed in as a parameter to the Action Handler

To create an example for an Action dispatched with data, I create a new Action Handler and call it with a locally created JavaScript Object – see screenshot below.

The object variable “myObject” (1) in line 49 is just an example of a complex object that can be passed into the Action Handler. The object variable is passed as the second parameter to the “dispatch” function (2), which dispatches the “DIRKS_ACTION_WITH_DATA” Action.

The new Action Handler just gets the “coeffects” passed in as a single value and prints out the structure of that JSON object (3) using the “JSON.stringify()” method.

find_real_file.png

The output in the console window of the web browser, after the button was clicked, looks like shown in the screenshot below.

The first line at the top (1) indicates, that the following output was generated by the new Action Handler. The output of the “coeffects” is showing the object in detail. You can see, that the “action” element (2) of the “coeffects” holds Action specific information. The data passed into the Action Handler can be found in the “payload” element  (3) of the “action” element.

find_real_file.png

Having that figured out, it is quite easy to consume the data passed in, like:

console.log(coeffects.action.payload.objVar1);

Feel free to play along with the new finding and get familiar with the concept and where and how to fill in the bits and pieces to chain up the passing of parameters from one function (e.g in an Action Handler) to another Action Handler.

As we will see later, you can use the same mechanism to communicate from your Component to any of your ancestor components (parent and/or parent-parent and/or parent-parent-parent, etc.).

 

 

 

Step 10 - Use life-cycle Action Handlers

For the previous steps shown, we always created our own Actions and Action Handlers for “custom Events” to be dispatched.

Besides that, there are some so-called “life-cycle” Action Handlers that are dispatched automatically by the NOW UI Components Runtime and which you can also use for your specific needs. They are dispatched, e.g. when the Component is instantiated or the Component throws an error.

To utilize these life-cycle Actions, you need to import the {actionTypes} from the “@servicenow/ui-core” library.

find_real_file.png

This import makes the names of the Life-Cycle Action Handlers available, which can then be implemented like shown in the examples below.

 

[actionTypes.COMPONENT_BOOTSTRAPPED]

find_real_file.png

The Action Handler "[actionTypes.COMPONENT_BOOTSTRAPPED]" is called automatically by the runtime as soon as the Component is initialized, and BEFORE it is displayed the FIRST time.

That way, the view function leverages the "bootStrapFlag" element of the state, without having it defined in the "initialState" object. Because the "[actionTypes.COMPONENT_BOOTSTRAPPED]" life-cycle Action Handler is called first, the value will already be available in the view when shown the first time.

find_real_file.png

 

[actionTypes.COMPONENT_PROPERTY_CHANGED]

The [actionTypes.COMPONENT_PROPERTY_CHANGED] life-cycle Action Handler is called each time, a property of the Component is changed (e.g. when the parent Component passes a new value down to the component).

The example below shows a "cascade" of the [COMPONENT_BOOTSTRAPPED] (1) life-cycle Action Handler, which (when triggered) changes the COmponent's Property called "internalProp2". This change of the Property will trigger the [COMPONENT_PROPERTY_CHANGED] life-cycle Action Handler, which in turn will update the "state" element "bootStrapFlag". This in turn is shown in the Components output immediately.

find_real_file.png

 

Note:
There is also another life-cycle Action Handler available for you. Just review the documentation on the Developer Homepage at:

https://developer.servicenow.com/dev.do#!/reference/now-experience/paris/ui-framework/main-concepts/...

 

Challenge:
Review the content of the different payload and content of the "coeffects" of each life-time Action Handler to get familiar with its usage!

 

 

 

Step 11 - Using nested Components to "bubble-up" Actions

As mentioned in the introduction of this article, Actions can not only be triggered from within the same component, but also from events that are dispatched in any child (or any descendant child-chid) component.

 

Add another Component to the Project

Let's create a new Component inside of the project.

As this here is NOT a copy/paste show, you need to do something now. Only training your muscles will make you get stronger 🙂

Create a new sub-folder in your project below the "src" folder and copy the shown files inside. Modify the "index.js" file to the content of the screenshot below.

find_real_file.png

The important thing to mention here is:

  • the Property "somePropValue" with the default value "unset" in code line 30.
  • the usage of that Property in the output / the "view" of the Component, so that you can see the content of that Property on screen
  • a button defined in line 14 to line 20, which dispatches the Action "DIRKS_HTML_BUTTON_BUBBLES" when clicked
  • an Action Handler (line 33-35) getting triggered on that Action and which logs some string to the web browsers console log.

Save all files and then add that new Component (as a Sub-Component) to the first initial Component we worked on previously - see screenshot below.

find_real_file.png

First, import the new Component (in line 5) into the main Component, so that it is accessible and usable from there (1). Second, just add the Components into your JSX part returned from the "view()" function (2), just like you can see in line 33 above.

Saving and executing this step, will result in the following output in your browser.

find_real_file.png

The red box shows the content of the new Component, that we just added to the project. Note, that the value "unset" of the Property is shown (marked in yellow), which is the "default" value.

 

Pass in a value to the "Sub-Component" (Properties drops-down)

Now, this is great stuff!!

Let's pass in the current value of the "clickCounter" state element value down at property to the sub-component, that we just added - see screenshot below in line 34.

find_real_file.png

This results in passing the value each time again down to the sub-component, as soon as it is changed leveraging the "updateState()" function.

In our previous implementation (if you followed bravely the steps above), the button of your MAIN Component will increase the "clickCounter" each time it is clicked by one. We already show this value in the MAIN Component to review the current value.

Now, we pass down this value (line 34) to the Sub-Component, which receives this value in the "somePropValue" Property. This Property in turn is reflected in the output of the Sub-Component (look at code line 12 in the screenshot below, showing the sub-components code).

find_real_file.png

The output looks like shown in the screenshot below. Each time, you click the upper button (of the main component), also the property of the Sub-Component is updated! That is a quite cool automatic process, which really makes the UI be up-to-date! I like it!

find_real_file.png

Clicking the button (1) of the main component updates the "clickCounter" of the main components state and is reflected in the output (2). At the same moment, the value is passed down to the sub-component to the property and shown in the output (3).

Did you get the context? Have you been able to follow the chain of things happening?

If you have some doubts, please go back some steps and take some time to review the example. This will become a basic principle for you very soon!

 

Catch the Actions from the "Sub-Component" (Actions bubbles up)

Review the Action and Action Handler implemented in the Sub-Component in the Screenshot below.

find_real_file.png

Now, add the SAME Action Handler to the main Component, with the difference to change the console log output a bit. We want to see in the console, which Action Handler was called by the Action dispatched in the Sub-Component. The screenshot below shows the new Action Handler in the main Component.

find_real_file.png

Save the changes and test your changed in the Web Browser

Clicking the "Bubble Actions" (1) button (which is located) in the sub-component, now will trigger the Action Handler of the Main-Component (2) and ALSO the Action Handler of the Sub-Component itself (3).

find_real_file.png

This proves, that the Action was caught by the sub-Component, but also by the "parent" (ancestor) of this component.

 

Findings

That is mainly, how components communicate with each other (Properties drops-down and Actions bubbles up). Keep that in mind. And siblings CANNOT communicate directly to each other!

Above, you learned how to put "payload" data to the dispatched Action. That way, you now also can pass data up from your sub-/child-Component to your Parent Component.

 

 

YEAH !!! That was a quite long ride down the line !!!

Finally, you made it!!!

 

 

Wrap up

Thanks a lot to stay with me until here in my article. All things written here are based on what I understood from the examples, the documentation, and from my own experience. If there is something you may figure out to be different in fact, then please let me know about that in the comments below.

The whole topic of Action Handlers is a bit wider than written down here. But that leaves space for an "advanced topic" article. Whoever knows what the future may bring.

I hope it was easy for you to follow the examples from above, and you learned some new stuff. At least, if I was able to de-mystify some things around the NOW UI Experience Components development, that makes me happy.

I welcome your comments to this article and also welcome some suggestions for topics you would like to be covered in upcoming articles. Any questions are also welcome. Let's collect as many details as possible.

 

 

Thank you for reading, and I hope you enjoyed this article.

Please provide your feedback on this article in the comments below.

If you like it, just mark this article as helpful and bookmark it using the "Bookmark" button above for later access.

Have fun and built something on ServiceNow!

Dirk

---------------------------------------------------------------------

If you like to also review my other articles on the ServiceNow Community, please have a look at the overview here:

Overview of my articles

NOTE: The content I provide here is based on my own experiences and does not necessarily represent my employer's views.

 

 

Comments
Kush Bajpai3
Mega Guru

A nice article indeed.
Could you please also post an article on using Hooks. 
I think hooks used in Now UI Components are a bit different from what is being used in React. 

Thanks,

Kush

V_ Wagner
Kilo Guru

Hey,
thank you for this nice post.

Is there a way to automatically create the actions for the ui builder, i.e. add it to add sys_ux_event and add those to sys_ux_macroponent?
Right now I have to add them each time again after I deploy my components.
Since all the components in the scope have to be deployed, its quite annoying to do it all over again for a small change...

Thank you!

Lon Landry
Giga Guru

Sadly, due to restrictions I cannot utilize the below tools:

  • now-cli in version 18.0.0 (note, that Version 18.0 currently only supports PARIS and NOT Orlando)
  • npm version 6.14.6
  • nodejs version 12.18.3
  • VS Code for development (any current version will be fine)

But, the diagrams and structure explanations are priceless!

Thank you so much for your hard work... 

Version history
Last update:
‎10-18-2020 01:14 AM
Updated by: