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

This is my second article about the NOW UI Experience Component Development.

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 navoigates you to my first/previous article about NOW UI Experience Components):

Fast Track to your first "Now Experience UI Framework Component

In this article here, I show you the next steps you can take, after you learned how to create NOW UI Experience Projects and how to build and deploy your first component.

After this initial ignition, take some time now to get familiar within the next steps and explore the new environment.

You will learn, how to add more Components to your Project and how you can (re-)use your own created Components inside your projects. That way up (or down - depending on your standpoint :-)) you can break  down your work in smaller chunks, that build up the final result as your "solution".

Generally, you will not create just ONE BIG component, which does all the heavy lifting of your implementation. For a better design, you are very welcome and invited to break down the big picture into smaller (and mostly) reusable pieces (Think about the good old LEGO times - or whatever construction kit you had in former times).

 

Scenario

I want to create one Component (2), which displays a HTML table, so that I can reuse the (indeed very simple) table component more that once in my main Component (1). Just for demonstration purposes, I will create another (even more simple) Component (3) that shows a HTML Link, so that this can be used as subcomponent from the HTML Table Component.

 find_real_file.png

You can take this as a baseline for your own projects later and improve this for your own Use Cases. The resulting project is NOT meant to be a nice and "ready-to-be-sold" Component.

My intention here is just to show you about the concepts and teach you about how things work under the hood, so that you know how to play the game. You are invited to become creative on your own.

Just write your ideas or improvements down in the Comments - I am interested in your creativity!

 

Outcome

The result, that you will get by following down this article is:

  • A new Now UI Experience Project having a number of custom Components created inside of it
  • You learned about the project structure and the main line-up of the files to make you magic happen
  • You learned how to nest your Components to reuse them
  • You learned about managing Component Properties
  • You learned how to pass Parameters from one Component to another (as Properties)
  • You learned how to set up those Parameters (Properties) in ServiceNow within Landing Pages
  • You learned about JavaScript De-Construction - if you follow the Challenge at the end of this article

 

Environment

I am doing this develpment 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>

find_real_file.png

I am using the following tools and versions

  • now-cli in version 18.0.0 (note, that the 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)

 

Hint:
When I tried to install the "now-cli" globally on my MacBook, I ran into some issues, which I personally did not want to solve with "nvm" etc. So, I installed the "now-cli" "locally", which is just done by omitting the switch "-g" switch in the "npm install" command for the "now-cli" (see below in the step to install the latest version of "now-cli").

If you want to read the experience of @Andrew Albury-Dor on installing the "now-cli" globally on MAC, just read his blog at the link mentioned below:

https://andrew.alburydor.com/posts/2020-03-20-nowui-part1/

 

 

Step 1 - Update your "now-cli" to the latest version

Open your command prompt (cmd.exe for Windows)

NOTE: Limitations that exist today (as of 10.10.2020):

I just learned yesterday, from @Brad Tilton's introduction on creating NOW UI Experience Components, that the "now-cli" in Version 17 is currently used for the development on the ORLANDO Release, and that Version 18 of the "NOW-CLI" ONLY works on the PARIS Release.

This is expected to change in the future, so that the most current "now-cli" version will work with all supported SerivceNow Release Versions, but currently, this is a limitation.

You can find Brad's Video here:

Getting Started with the Now Experience UI Framework

As I am working on a PARIS Version PDI, I am using version 18 from the "now-cli" (see screenshot below):

find_real_file.png

Installing the ORLANDO version of the "now-cli" will be done with:

npm install @servicenow/cli@orlando -g

Also refer to the documentation on the ServiceNow Developer Homepage for the now-cli at:
https://developer.servicenow.com/dev.do#!/reference/now-experience/paris/cli/getting-started 

 

 

Step 2 - Create a new UIX Project for this workshop

Follow the steps below to create your new "NOW UI Experience" Project (refer the colored numbers in the screenshot below):

(1) create a NEW project folder (in your file system, e.g. with Windows Explorer) on your local machine

NOTE/ATTENTION:
Make sure to NOT create the project folder on some cloud-drive folder (like iCloud, OneDrive, etc.) and also I recommend not to put it in your "users" folder on your machine (at least on the Windows Box). I just created a separate folder on my "C:\" drive and created an empty folder in it (like "C:\Daten\NOWUIX").

The folder you use for your component must be EMPTY! If you install "now-cli" locally (e.g. on your MacBook) in your project folder (without the "-g" switch), you just need to create another empty sub-folder within your new Project's folder to place your project's source files in it. That worked also perfect for my on my MacBook.

(2) Log in to your ServiceNow Instance with the "now-cli" command. Log into that Instance where you later want to use that Component (see the command in the screenshot below). Note, that the "now-cli login" command shows the version of your ServiceNow you connected to, which is "Paris" in my example.

(3) Next, create the scaffolding (the skeleton) of your new Project using the "now-cli project" command:

find_real_file.png

 After that, install all the project dependencies with the command (see the results in the next screenshot below):

 > nmp install

This may take a while, because there is a lot of stuff to download and store into your project folder

find_real_file.png

Your project folder now is on "heavy load". In my case, the folder has more than 750 MegaBytes (see screenshot below) and more that 88.500 files. Not bad for a "Hello world" kind of project :-))))

 find_real_file.png

So far, that are the steps you can already learn (in more detailed steps) in my previous article that I wrote about the NOW UI Experience Components. You can find that article by following the link below:

Fast Track to your first "Now Experience UI Framework Component

 

 

Step 3 - Review the new Application Scope in ServiceNow

After the Project was created (online WITH using the "now-cli login" before and NOT using the "offline" option), you can review the newly created Scope in your ServiceNow instance in the Application Picker (see screenshot below). Login to your instance, or refresh the window to make that Application/Scope visible.

find_real_file.png

Note:
The new Scope also requires a new Local Update Set in your instance, which you can review by navigating  in the Classic UI of ServiceNow to:

> System Update Sets > Local Update Sets

You can look into that update set, and find the changes that will be deployed for your component project later. Everything that happens during your development cycles will only be reflected here, after deploying your component to ServiceNow. Otherwise, you will not affect that Update Set here.

Keep that in mind, if you want to review one day, what makes up your Component in ServiceNow.

 

Attention:
The Update Set in ServiceNow will NOT hold your source-code of the Componet Project. That must be saved separately and outside the ServiceNow Instance. So, make sure to archive THAT version of the Source-Code, which you will use one day to deploy your Component(s). I recommend to use some Source-Control system like "GIT" (e.g. on "GITHUB") and also to make regular backups of your source-code to some separate place. Otherwise you will think about my words - one day...

 

 

Step 4 - Open and review the new Project in VS Code

There is already one first starting component in your project, that was created by the "now-cli project" command (as scaffolding step) inside your project folder.

Open VS Code and open the project folder, that you just created above, to see the files in your project folder.

The screenshot below shows the project file&folder structure in the left side ("Explorer") of VS Code, and the content of the "index.js" file for the automatically created Component.

Note:
The name of the project was set to "demo-02" and that is also the name of the first component created by "now-cli project". The name is prefixed with the new Application Scope, which was automatically created in ServiceNow on behalf of the "now-cli project" command.

find_real_file.png

The "index.js" file, marked in the screenshot above (in the left side in the Application Explorer of VS Code), mainly holds the "createCustomElement()" (1) function, which will be called from the (ServiceNow and/or Development) Runtime environment, as soon as this component is "started" (instantiated, shown,...). This happens in your development/test environment locally as well as using your component in Workspaces later in your ServiceNow instance.

We will have a closer look at the "createCustomElement()" function in a later step below. Stay tuned !!

So, the "starting" point for the code to execute for that Component (Project) can be seen within the function "createCustomElement()".

Note:
All Components, you will create, will have their OWN "createCustomElement()" function, which is locally for each particular component. But ONE component is the "starting component", when you "start" your project (with "now-cli develop"), and this is by default the Component, that was created from the "now-cli project" scaffolding step.

Also note, that the project already THREE "index.js" files on different folder levels inside of your Component project folders.

The one "index.js" file locally for your first/main Component of your project is shown in the screenshot above. Looking one more folder up in the folder hierarchy (in the "src" folder of your project), you will find the "index.js" file shown in the screenshot below:

find_real_file.png

This "index.js" file (1) just imports (2) the whole (main) Component folder (3). Normally you do not need to touch this file - at least for the next steps to go here.

 

The top-most "index.js" file (1) - shown in the screenshot below - also just includes one line (2). This statement exports the modules, which are defined in the "package.json" file (3) and which makes up the whole "bundle" as the outcome of the projects folder contents.

find_real_file.png 

 The screenshot below shows the content of the "package.json" file (1) including the "module" definition (2😞

find_real_file.png

Line 16 of the "package.json" file show, what "module" means. It references to the "src/index.js" file described above. The one which IMPORTS the main Component of your project.

Now, surfing around in some of the files of the project, let's review what makes up a Component just after it was created in the basic version from the "now-cli project..." command.

 

 

Step 5 - Review the "createCustomComponent()" function

To get a closer look at what happens, when a "NOW UI Experience" Component is utilized, let's drill into the details of the Component's "index.js" file.

Using VS Code is fun, because it helps to drill into and drill through different artifacts of the project. Hovering with the mouse-pointer over the function call of the "createCustomElement()" will pop up a small tooltip window (1) above the function name (like the one shown in the sceenshot below): 

find_real_file.png

The tooltip shows the function definition of "createCustomElement()" which states, that it expects TWO parameters when called.

1) The first parameter called "elementName" is a "string" type (1) and just is the name for the newly created custom element (the parameter in the function definition AND in the function call, both are marked in magenta color in the screenshot above)

2) The second parameter is an Object called "config". This Object of type "ComponentConfig" has a predefined structure and "configures" the Component, which will be created with the call of the "createCustomElement()" function call. Both, the parameter in the function definition AND in the function call are marked yellow (2) in the screenshot above.

The source code generated by the "now-cli project" call is creating this complex object (of type "ComponentConfig") inline with the function call. The creation of the second parameter spans five lines, starting with the leading "{" and ending with the trailing "}" - all marked yellow in the screenshot above.

So, the function call of "createCustomElement()" just ends at the bottom of the screenshot above (the closing ")" at the list line marked yellow).

This is the fastest and easiest way to create that Object, but the more you will implement inside of your component later, the better it may become, to "break-out" parts of the object into separate code parts. This can be done inside the "index.js" file, OR can also be done by separating some parts of the Object into separate JavaScript source code files.

That depends on your own preferences or on your coding standard you have set up. Also the size of source code parts may be an indicator to break this construction of the "ComponentConfig" object into separate chunks. Creating this "ComponentConfig" object over hundreds of lines of code, may become uncomfortable one day.

To review the structure of the "config" object parameter (of type "ComponentConfig"), you can (of course visit
The ServiceNow Developer Homepage), or you also can right-click on the "createCustomeElement()" function call in VS Code and select "Go to Definition" - see screenshot below:

find_real_file.png

This opens a new source-code TAB in VS Code, showing the function definition of the "createCustomElement()" function. Furthermore, the definition of the "ComponentConfig" object is found here in the file that opens in the new TAB.

The screenshot below shows the "index.d.ts" (TypeScript) file (1), that contains the function definition for the "createCustomElement()". The file is locates in the "typings" folder of the "ui-core" folder (2), which in turn is located in the "@servicenow" folder of the "node_modules" folder of your project's main folder - try to review that in your editor / file-system / VS Code / whatever... as well!

Note:
That file was not added as part of the scaffolding process with "now-cli project", BUT it was added to your project's folder when you loaded the project's dependencies using the "npm install" command AFTER the scaffolding finished.

find_real_file.png

In the screenshot above, you can find the "createCustomElement()" function (3) definition, which in turn utilizes the "ComponentConfig" interface / object (4).

The "ComponentConfig" contains an element called "properties" (5) on code line 11. This element can contain sub-elements defined by a "PropertyConfig" - we will drill down into that later down here - keep the faith!

As you can see, that "ComponentConfig" object (sorry to all professional JavaScript developers to call this an "object", but this may be OK for this learning) leverages the "view" function (6), which is responsible for the visual representation part of the Component. The return value of that "view" function contains the HTML part to be shown in the end-user's browser.

Additional Information:
The "view" element (6) of the "ComponentConfig" object (remember: where "ComponentConfig" is the second parameter of the "createCustomElement()" function) is a function, which renders the Component. This function is already separated for you, by the scaffolding step done with the "now-cli project.." command.

Remember from one of the screenshots above, that the "view" function can also be found in the "index.js" file (see screenshot below in line 5). It is referenced in line 13 (inside the "ComponentConfig" object; the second parameter of the "createCustomElement()" function).

If that all sounds a bit "too nested" for you in this moment, please take a few minutes to understand, that there is an object defined as the second parameter of the "createCustomElement()" function call (in line 11).

find_real_file.png

Note:
The statement "view" in line 13 (1) is a shortcut for the definition of the element "view" of the "ComponentConfig" object. The long version of that would be "view: view". In the long version of the view element, you could even rename the "view" function (2) in line 5 to any name you like.

If you rename you "view" function to "funkyViewName", you can reference it inside your "ComponentConfig" (in line 13) as "view: funkyViewName".

Remember:
The view function returns the visual representation of the Component, which leverages JSX syntax, which allows some sort of mixture between HTML and JavaScript. You can search Google for "JSX" to learn more details about it (follow some "REACT" links, that may be good friends).

This is the very basic thing needed to understand and we will concentrate on the two functions ("view" and "createCustomElement") today.

 

Great!
That was a bit research and investigation about where you walk around, when playing with the NOW UI Experience Component development.

Take some extra time to get familiar with that BASIC structure of the Components source-code files and code content, to understand how pieces are put together and how they roll up to your component project.

 

As the next steps, we will create more components (inside of the project), which can be later reused and customized by passing property parameters in.

 

 

Step 6 - Create a second Component in the Project manually

Each Component is best located in it's own sub-folder

Create a new folder for the new component "x-269923-table-list" (or what scope name your prefix ever may be, replace it with your scope name) directly below the "src" folder in your project folder. You can see the main component created by the "now-cli project" call (1).

Note:
I named the folder including the Scope prefix ("x-269923") followed by the name of my choice for the new  component.

I then copied the "index.js" and "styles.css" files (2) from the "x-269923-demo-02" folder into the folder of the new component and opened the "index.js" file in the Editor.

The first thing I changed here is the name of the component, which is the first parameter of the "createCustomElement()" function (3).

Hint:
Make sure to rename the component to the same name of the folder to not getting things mixed up!

find_real_file.png

Add some HTML/JSX to the "view" function

In my example here, my "table-list" component is intended to show a small HTML table, that we will fill up with some dynamic content step-by-step.

For the first iteration, just add the following code to your "<div></div>" of the return in your "view" function.

            <br></br>
            <table border="1" width="400">
                <tr>
                    <td>Parameter</td>
                    <td>Value</td>
                </tr>
            </table>

 Your "index.js" file of the new/second component should now look like shown in the screenshot below:

find_real_file.png

The output of this component now will just look like a simple HTML table shown in the next screenshot:

find_real_file.png

Wait a minute, YOU cannot see it right now, we need to "implement" it first within our main Component. Move on to the next step.

 

 

Step 7 - Leverage the new Component in the main Component

Now having an own (sub-) component, I want to use/reuse it in my main component. The "main" component is the one, that was created with the scaffolding step in my project with the "now-cli project" command.

Using the new "table-list" component inside my main component is very simple.

Open the  "index.js" file (1) from the main component in VS Code (like shown in the screenshot below), and add the two lines:

(2) line 4 IMPORTS the new component to the "main" component, so that it is known and can be used

(3) Thanks JSX syntax, instantiating the "table-list" component is easy as adding a HTML-like tag (line 10).

Just add the name of the component in the code like you would do with an HTML tag.

find_real_file.png

In this case, the "table-list" (the second) component is leveraged as a kind of "sub-component" or "child-component" to the main "demo-02" component.

You can use that Component any number of times now. Everywhere, where the component is inserted in the JSX, it will appear in your output in the browser. Each will become a separate "instance" of that Component, holding it's on values,. properties, etc..

Running / using the Component ten times, just needs to copy the "<x-269923-table-list></x-269923-table-list>" ten times to the code 🙂

So, your component is already re-usable and you already did some separation of concerns by implementing separate components. (That's the purpose and the reason for the name : "Component" - AHA - haha ;*Q ).

 

 

 

Step 8 - Run and Test your new Components

To run and test your new Component, open a new command line interface (cmd.exe) and run the commend:

> now-cli develop --open

This will "compile" the new Component, start a local WebServer to locally publish the component(s). Using the "--open" option of the command, will automatically start/open your default Web-Browser and show the component on a new tab (see screenshot below):

Note:
The testing (by default) starts with the component, which I call the "main" component above - which in this case is the "demo-02" component.

find_real_file.png

The local Web-Server runs on port 8081 by default (1) and is reached at the URL "http://localhost:8081".

Note:
The local Web-Server is called from the Web Browser WITHOUT using a SSL connection, which means it will NOT be reached by using "https" (secure)!

The first line (2) in the Browser Window ("This is the main component....") is the text, which was entered directly in the "demo-02" Component's "View" function.

The table below (3) is inserted into the HTML as a kind of "child" or "macro" at the position, where it was placed in the JSX part in the "view" function. This is the content of the "table-list" component, which is used by the main Component.

Now you know how to create new components inside of your projects and also how to reuse them inside of other components of your project.

 

 

 

Step 9 - Why to use Properties in Components

So far, the "table-list" component can be re-used as many times as desired in any other component.

Note:
Using Components in a "self-containing" (recursive) way does not make any sense. Do not try that!
In other words, you cannot create a "Papa" component, which will call the same "Papa" component itself (same is true for a "Mama" component - by the way..)

Anyhow, the content shown from the current implementation of the "table-list" component is static, and will always be the same. This is not THAT interesting and fun in the long term, to utilize the same table ten times on screen.

But what, if your component is e.g. a button and you want to have different texts shown on the button?
Or if you want your table-list component to show "dynamic" content (e.g. a dynamic table..)?

Of course, you can create separate components for different table content or an "OK" button and another one for a "Cancel" button, but this is not a good practice. It will be more obvious to have just one table or one button component, which can be configured accordingly.

As there is any kind and number of configuration options, you may want to send to your components, you can define any number of Properties inside your components. The good thing is, that you can later pass-in values to these Properties to make your component behave depending on those "Parameters".

The next two steps will show you how to define Properties within your components and then, how to pass in values to your components.

 

 

Step 10 - Create and use Properties in the "table-list" Component

Creating properties in your component is the first step, to make them available for use INSIDE of your component.

The screenshot below shows the "index.js" file of the "table-list" component, which was enhanced a bit, to show up the basic usage of Properties.

Add the "properities" part (in line 31++) to the "createCustomElement()" function (in fact to the "ComponentConfig" parameter object) as marked in blue below (1).

find_real_file.png

Take care about the syntax, which may be a bit unfamiliar to you (like it was to me).

Generally, you add the "properties" attribute to the second parameter of the "createCustomElement()" function. Thats why the second parameter is enclosed in "{}" (object notation line 28 "{" up to line 37 "}") like

createCustomElement('component-name', {})

Inside those "{}", you define different attributes as Name/Value pairs like "properties: {}", where "properties" is the name of the element and "{}" hold the "object" assigned to that element.

So, just writing "properties: {}" is completely valid. It just means to define the properties element with an empty object (which results in having NO properties defined at all)

But if you want to define Properties inside, you again need to define Name/Value pairs; one for each property / element you want to have assigned to your Component.

 

There are three properties I created in the source-code shown in the screenshot above: 

a) the first Property is called "headline" (code line 32) and has an empty object assigned "{}". This is valid and the property is fully available and accessible afterwards.

 

b) the second Property is called "firstname"(code line 33) and has an object (of type "PropertyConfig") assigned to it. That object has again a number of Name/Value pairs, which in this case is the attribute "default" and the value "<firstname>".

In this case, this results in having a default value assigned to the Property "firstname". The default value will be used, if no value concrete values is passed in to that Property and the Property was not set to any given value elsewhere.

 

c) the third Property (code line 34) DOES NOT WORK. The name containing an underscore ("_") does not work.

  • Who ever know why, please put the answer down to the comments of this article, please!

Note:
So, keep in mind to use NO special characters in the names of Attributes (even no underscores) !!!

find_real_file.png

As soon as the Properties (1) are defined in the second parameter ("ComponentConfig") of the "createCustomElement()" function , they can be used inside the "view" function. They are passed in (2) to the "view" function via the "state" parameter (first parameter of the view function).

The object notation to access these properties is like show at (3), (4) and (5). You access the properties object via the "state" object, which is passed in to the "view" function as first parameter (see line 5 in the screenshot above). So the dot-walk notation to the properties is "state.properties.nameofproperty".

The curly braces "{}" around the properties (e.g. "{state.properties.headline}") just instructs to fill in the value of the Property (variable) to where it is placed inside the JSX code of the "view" function.

After saving the changed code, the Components in action will look like shown in the screenshot below:

Note:
Run "now-cli develop --open" to show the result oin your default Web Browser.

find_real_file.png

You can see, that the "headline" property (1) is empty and does not show any content. The "firstname" Property is configured with the default value of the string "<firstname>", which is also shown (2) correctly. And the definition of the Property (3) "first_name" (including an underscore in the Property name) results in an empty value as well (caused by the property name including an underscode - who ever knows why?!).

Here below, you find the full source code of the "index.js" file (for copy/paste):

import {createCustomElement} from '@servicenow/ui-core';
import snabbdom from '@servicenow/ui-renderer-snabbdom';
import styles from './styles.scss';

const view = (state, {updateState}) => {
	return (
		<div>
            <br></br>
            <h3>Headline: {state.properties.headline}</h3>
            <table border="1" width="400">
                <tr>
                    <td><b>Parameter</b></td>
                    <td><b>Value</b></td>
                </tr>
                <tr>
                    <td>firstname</td>
                    <td>{state.properties.firstname}</td>
                </tr>
                <tr>
                    <td>first_name</td>
                    <td>{state.properties.first_name}</td>
                </tr>
            </table>
        </div>
	);
};

createCustomElement('x-269923-table-list', {
	renderer: {type: snabbdom},
    view,
    properties: {
        headline: {},
        firstname: {default: '<firstname>'},
        first_name: {default: '<first_name>'}
    },
	styles
});

Note:
Using JavaScript "De-Construction", you can break down the "state" object (the first parameter of the "view" function) into smaller accessible variables (see "Challenge - JavaScript De-Construction" at the end of this article).

 

Now that we have Properties defined in our own custom Component and that we know how to utilize them in the output of the "view's" HTML, let's see how we can pass-in values to the Component from "outside" of the Component.

In the video to the great "CCW2905" course on nowlearning, @ben.kennedy.snc told about the Properties that drops down to components. I think that means, that you "inject" properties into components, as some sort of configuration to them (like the text of a button, or the color of a background, etc.).

You can find the Community article to this course at: Link to the Communitiy Article to CCW2905

You can access the guidebook and video for the course over on NowLearning (I recommend to visit it!):

https://nowlearning.service-now.com/lxp?id=overview&sys_id=9a7864071bb4d4901759b8c11a4bcb3a&type=cou...

https://developer.servicenow.com/dev_app.do#!/event/knowledge2020/CCW2905

 

 

Step 11 - Pass values to the Components Properties

Now that we created the Properties in the (sub-) Component and also were able to define "default" values for them, I want to pass in some values to each instance of the component that I use.

The screenshot below show the "index.js" file (1) of the "demo-02" component. Passing in values is as simple as adding attributes to HTML tags (2), as you can see from the screenshot below.

There are to options to pass in values to the Component. The one is just passing in "simple" string values, and the second option is to also pass in complex JavaScript Objects, which makes the values injected much more efficient to be used. Think about passing in the content of a GlideRecord Query (as a JSON representation of the returned table records) to your component. That way, you easily can walk through the JSON data and display all the data from inside of your component.

 

OPTION A: Pass values by HTML Attributes

<my-component attribute='string value'></my-component>

The "attributes" of the used component (inside the "<...>") will define the values that can be sent down to the instance of the Component - always in String format. In this case, the "HTML attributes" will be mapped automatically to Now Component Properties. These attributes defined, are always of type String (inside the "<...>").

find_real_file.png

The result will look like shown in the screenshot below:

You can find the values passed-in from the main Component above. Compare the "headline" and "firstname" values given at line 11 and 12 in the screenshot above, and how the automatically were mapped to the properties we used before.

find_real_file.png

Note, that any "default-value" defined for your properties will be overwritten by the values passed-in, given as "parameters" or "attributes" when leveraging your Component.

Using the "table-list" Component multiple times in your parent/main "demo-02" Component may be done like shown in the screenshot below:

find_real_file.png

(1) and (2) both create separate "instances" of the "table-list" component, which exist separately on the resulting page. Parameters passed-in to each of the components, stays locally to them. Each instance of the "table-list" component holds it's own set of values for the properties. Components are separated from each other.

The results will look somewhat like shown in the next screenshot:

find_real_file.png

 

 

OPTION B: Pass values by using JSX syntax (complex JavaScript objects)

You can also pass in values of "complex objects" down to your Component, using JSX notation.
This is extremely handy!

You can pass in any object to your component. If you want to inject a complex object like a JSON object (e.g. a list of records), you can do so. That way, you can enhance the "table-list" component to show a real list of records.

<my-component attribute={JSX expression}></my-component> 

 find_real_file.png

The example shown in the screenshot above first creates a "complex" JavaScript object called "myobj" in the upper red box, and then passes this complex object down to the "table-list" component as the "propobject" Property in the second red box of the screenshot above. 

Try that out on your own and get experienced in that. Take some time to juggle with different parameters.

It will be worth it !!! 

 

 

Step 12 - Creating a third "Sub-Component"

This step is just to show you how to pass values down from a top-level component to a child-child component.

Create a new folder in your project under the "src" folder, just like shown in the screenshot below and copy the "index.js" and "styles.css" files from the "x-269923-table-list" directory.

Open the new "index.js" file (1) in the new folder (I called "x-269923-hyper-link") and add the code shown below to the source file:

find_real_file.png

First, rename your component to "x-269923-hyper-link" (2) and create the properties (3) with the two names "linklabel" and "linkurl". Remember to use your Scope name instead of "x-269923".

Modify your "return" code of the "view" function to contain only the one anchor tag (4) - like shown in the screenshot above. Both properties will be used inside this anchor, so that this new component just reflects an easy way to implement a hyperlink in other components.

Save all files!

 

 

Step 13 - Passing values down from the main component

Now, that we have the "hyper-link" component created, we will use it in the "table-list" component.

Review the source-code below for detail (of the "index.js" file of the "table-list" component). You should now be able to read and understand what is happening there.

find_real_file.png

Again, the first thing to do, is to "import" (1) the "hyper-link" Component to your "parent" component, which in this case is the "table-list" component.

Now, try to build this on your project like shown above! This is a small exercise for you. Yes! You can!

The results should look something like shown in the screenshot below:

find_real_file.png

 

!!! AWESOME !!!

Now you saw, how to create additional custom Components in your NOW UI Experience Projects, how to re-use then and how to pass-in values to customize the Components' properties.

Review this project and the steps above as often as needed to feel comfortable with the project structure, how properties are built up, how to pass in values as simple strings and how to pass in complex objects and work on them inside your components.

 

ADDITIONAL NOTES:
The steps shown here are used to drop-in values from any "parent" component to any "child" component. The child Component will always have a COPY of the values passed-in as parameters/attributes. Changing the values inside the child Component NEVER changes the values inside the "parent" Component (the Component passing-in values).

If you want to pass back values from the child Component to a parent Component, this is NOT done with properties. This will be done by Actions and Action-Handlers (not part of THIS article - stay tuned for upcoming articles in the pipeline). If you want to communicate to sibling components, you will need a combination of Action Handlers (bubbling up) and Properties (dropping down). You cannot "talk" directly to your sibling Components.

 

 

 

 

Step 14 - Publishing the top most Property to UI Builder

Now, that we learned about how to leverage Properties within your project, it is time to bring this Component Project to your instance!

But before we just go and deploy the Component Project to your ServiceNow instance, I want to show, how you can create "top-most" properties, that can be modified and configured in UI Builder inside of your ServiceNow instance, after the Component was deployed. This "injects" any configuration, you like to give your Component in the UI Builder (to design your Workspace Landing Pages according to property options).

Having this in place, you could e.g. configure a table-name as the principal input property to your component in the UI Builder, and the Component will display data from that table.

Any Component "published" (made visible) to UI Builder, will have it's own Properties exposed.

 

Create a Top-Level Property (in the main "demo-02" component)

Open the "index.js" file (1) from your main Component (here "demo-02") and add a Property like shown below in lines 41, 42 and 43 in the screenshot (2). This is a property of the "main" component. The intention is, to make this property availabe to UI Builder, so that you can configure it's value in ServiceNow.

Note, that this property has a default string value of "Hallo".

Use this Property in the "view" function to make it appear in the Component (3).

find_real_file.png

Running your component locally will look like shown in the screenshot below:

The Property "myprop" with the default value "Hallo" is shown in the first line (1) in the Browser window.

find_real_file.png

Because I want to be able to configure this Property value from within UI Builder in ServiceNow, I need to "expose" this Property to the UI Builder.

This can be done in the "now-ui.json" file (1), which lives in the top level of your Project's folder (see screenshot below).

find_real_file.png

Note, that you may need to add the "uiBuilder" section manually to your "now-ui.json" file. Change the "label" in line 8 (2) to the name, that your Component will have in UI Builder later in ServiceNow.

Add the "properties" (starting in line 14) section (3) as shown above. This is an array of property definitions. My example only defines ONE Property for the "demo-02" component. Note, that the "name" of the property is set to "myprop", which must exactly match to the name of the property declared in your Component (see above).

As soon as a value will be entered for this Property in UI Builder, this will be passed in to the Component inside of ServiceNow.

Add a "label" (line 17) and "description" (line 18) to make your Component Configuration look nicer in UI Builder. Note, that you can define, whether that Property is readOnly (here "false", to allow it to be changed in UI Builder). Setting the "required" (line 20) value to "true" would require that Property to be set in UI Builder. Here it is set to "false", which makes this Property value optional.

The "defaultValue" (line 21) given here, will OVERWRITE the default value set inside of the Component itself, for that property. So, if no concrete value will be set for this property in UI BUilder, the value of the "myprop" property will be set to "Victory!" 🙂

 

That's all to make your Properties "public" to UI Builder. You can add any number of properties exposed here and make your Component very flexible when implementing and leveraging inside your Landing Pages in ServiceNow. Note, that the exposed properties are always specific to EACH Component exposed to UI Builder. In my example, I only expose the one Component.

BTW: Do NOT forget to SAVE that "now-ui.json" file.
Also, riun a "now-cli develop" first, to make sure, your component still works fine.

 

 

 

Step 15 - Publishing the Component to ServiceNow

Now, it's time to go on stage!

Run the "now-cli deploy --force" command (1) to upload your component to your ServiceNow instance (see screenshot below).

You can see, that I did not deploy that Component for the first time, because the command first deletes some existing files and uploads the new versions of it (2).

find_real_file.png

Note:
Deploying the Component the very first time will work without the "--force" option, but will be needed for any later subsequent deployment. This switch forces to overwrite the existing component in your instance, if you deployed before. This is just a "security option".

 

The next step is not necessary, but will just show you the files, that have been uploaded to your instance:

Go to your ServiceNow instance and navigate to:

> System Applications > My Company Applications

This will bring up a list of Applications, including the one for the Components just published.

find_real_file.png

Click on the card for the Application, that shows the name of your Component. This will open the Application record, where the Component was uploaded to.

The screenshot below shows the "Custom Application" record (1), with the name given when creating the Component's project (2) and it's associated Scope (3).

find_real_file.png

The Related List "Application Files" shows the files that have been uploaded. You can open them, but they do NOT hold any Source-Code that you could modify.

Keep in mind, that ALL development regarding NOW UI Experience Components will happen outside of your instance. Maybe that will change one day - let's stay tuned.

 

 

Step 16 - Using the main Component in ServiceNow Landing Pages

Showtime!

Go to your ServiceNow Instance and navigate to "Landing Pages", which can be done in the PARIS Release like

> Workspace Experience > Administration > Landing Pages

find_real_file.png

Open the UI Page, that you want to edit and to make your new component appear on it.

find_real_file.png

Click on "Open in UI Builder" to open a new Browser Tab showing the UI Builder.

 

Switch to the "+ Add component" Tab (1) and drag (3) you new "Demo-02" Component (2) onto the Landing Page drawing canvas (like shown in the screenshot below).

find_real_file.png

Note:
The value "Victory!" is shown in the output of the component (4). You can open the properties pane on the right side for the "demo-02" component to see the property editor (5). The default value ("Victory"), set up in the "now-ui.json" configuration file, is pre-loaded to that field but you can adjust it as you like. The changes will be reflected immediately in the Drawing Canvas of the Landing Page, as soon as you leave the input field for that property

 

! WOAH - What a ride !

I hope you were able to follow the steps mentioned above.

If you have any questions or doubts, please give your feedback in the comments below!

 

 

 

Challenge - JavaScript De-Construction

Hey, still not enough? Do you want some extra? Some challenge?

All right. What is "JavaScript De-Construction"?

My definition would be: Breaking down complex objects into smaller pieces/parts of it for easier access!

 

Well first, you can only De-Construct, was Constructed before. In this case JavaScript Objects.

Note:
You can follow the steps below by using the Developer Console in your Web Browser (e.g Chrome). You can type in line-by-line mentioned below:

 

1) You surely will be familiar with the notation to create JavaScript Objects like:

var myobj = {varstr = 'NOW UIX'};

This defines a variable of type "object", which contains an element called "varstr" and this element contains the string 'NOW UIX').

You can print out this object with:

console.log(JSON.stringify(myobj,'',4));

The output looks something like shown in the screenshot below:

{
   "varstr": "Hello Seismic"
}

 

2) Create a more complex object

var complexobj = {address: {name: 'Donald', street: 'Main road', city: 'Home town'}};

This creates an "address" object, with three elements below that object.

Printing this out with:

   console.log(JSON.stringify(complexobj,'',4));

results n the output of:

{
   "address": {
      "name": "Donald",
      "street": "Main road",
      "city": "Home town"
   }
}

If you want to access the "city" element of the "address" object, you need to write (dot-walking down the path of the elements to address the "city" field):

   console.log(complexobj.address.city));

The output surely will be:

Home town

This is no problem so far, but if you want to access several "fields" from the address elements, you always need to repeat the "path" to the fields with the prefix "complexobj.address".

 

 

3) De-Construct the address object for easy access

To shorten the "access-path" to the fields, you can de-construct the "complexobj" object variable like:

var {address} = complexobj;

This will create a new variable called "address" and assign it the element with the same name ("address") from the "complexobj" object (in fact "compleexobj.address").

From that moment on, you can access the address directly with:

console.log(address.city);

And the output will be again:

Home town

That was your first De-Construction! Now you broke (de-constructed) your complex object into smaller pieces, which can be accessed in an easier manner, without typing always the whole dot-walk path to each element.

This may look a bit unuseful for this small example, but think about quite complex objects, where you have several nestings of elements. In that case, it may make sense to create those "shortcuts". 

 

 

4) Changing the value of a De-Constructed variable

But what happens, if I now change the value of the "De-Constructed" variable, like:

   address.city = 'Gotham';

Will that also affect the original "address" inside of the "complexobj" variable?

 

The output of:

   console.log(address.city);

is for sure:

Gotham

 

The output of:

   console.log(complexobj.address.city);

is also:

Gotham

 

Well, that proves that you did not COPY the part of the "address" element to a new variable, but that you just created a "shortcut-POINTER" to that part of the object. This makes sure that you can address the variables in either way and you can  be sure, that the values are always reflecting the one original central object data.

 

5. De-Construction Syntax details

The long version of the syntax allows to rename the variable created. If you want your de-constructed variable to be named different than the name of the element in the complex object, you can use the syntax below:

   var {address: addrobj} = complexobj;

This creates a new variable called "addrobj", which gets the "shortcut-POINTER" to the "address" element.
Afterwards, you can access the new variable with:

   console.log(addrobj.city);

 

 

6. De-Construction for NOW UI Experience Projects

De-Constructing can be found for the Component development as well, like in the definition of the "view" function of your components.

The standard definition of the function is like:

   const view = function(state, helpers) {};

This defines the "view()" function with the two parameters "state" and "helpers". The first parameter "state" is a complex object, as well as "helpers".

Changing the definition to:

   const view_function_name = function({properties}, helpers) {};

will create a object variable called "properties", which is the "shortcut-POINTER" to "state.properties".

Then, you can access the properties like:

   properties.propname;

instead of:

   state.properties.propname;

Knowing the details of the "magic" (like most the time) makes the "magic" disappear, but also makes you understand what is happening under the hood!

 

Further detail on that topic can also be found here:

https://hacks.mozilla.org/2015/05/es6-in-depth-destructuring/

 

 

 

 

Wrap-up

Digging into the details of the NOW UI Components may feel a bit complex from the first starting point.

!! DO NOT GET AFRAID OR DISAPPOINTED, IF YOU NEED SOME TIME TO FIGURE OUT THE FIRST TIME !!

Repeat the steps from above in your own projects.
Create several different projects and components and deploy them to your instance.
Try this on different computers to get familiar with the setup and the environment.
Walk through the folder structure of your project BEFORE and AFTER the "npm install"
Walk through the different files and try to "Go to Definition" for some ServiceNow functions to learn about the structure of the functions and objects used.

Best practice is : Best to practice!

Talking about events (Actions and Action Handlers) will be one of the next topics I will cover. So, give me your feedback, please.

I hope you like the Development with this new technology as much as I do. I hope you got a nice boost on your learning curve for NOW UI Experience Components on reading this article.

  

 

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

Please provide your feedback to 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
Matt Hernandez
Tera Guru

>>Attention:The Update Set in ServiceNow will NOT hold your source-code of the Componet Project. That must be saved separately and outside the ServiceNow Instance. So, make sure to archive THAT version of the Source-Code

I have a question on the part about deploying update set. Is this saying to archive the update set containing the initial deployment? Or is it just saying to make sure and archive your source code somewhere?

Tommy Jensen
Mega Guru

Your updateset will only contain the compiled version of the component.

If you ever want to make changes you must save your source code because the only way to change the component is through the deploy process.

DirkRedeker
Mega Sage

Hi Matt

I agree with Tommy's answer.

You need to store your source code in a separate safe place. For things like "Script Includes", "Client Scripts", "Business Rules", "Service Portal Widgets", etc., which are created inside the Platform, the source code is also stored in your instance.

For NOW UI Experience Components, the development takes place outside the instance, and when deploying the Component / Project, the source files are not uploaded to ServiceNow - just a "compiled" version (minified, etc.).

So, you can save the whole project folder separately.

Note:

The "node_modules" folder, which grows up to hundreds of Megabyte "normally" does not need to be saved WITH that project, because they can be restored from "npm install" at any later time.

But it is up to you, to also store this folder with your project.

Personally, I just save the files and folders EXCEPT the "node_modules" - especially for sharing or exchanging files.

Let me know how you plan to arrange.

BR

Dirk

Matt Hernandez
Tera Guru

Thanks, you guys removed my confusion. You were just pointing out that the source does not go into the instance, so must be maintained elsewhere. I did understand that, just got confused about something you said because my understanding has been shaky on how these components are initially deployed to some later instance. I thought maybe you were saying to export & save the initial update set and use it for deployment in the future, to some other instance instead of deploying from the CLI.

Tommy Jensen
Mega Guru

When it comes to moving the component from dev to test and prod then you can do that from inside ServiceNow.

Goto the "My company applications", select the new application and chose publish to updateset. This updateset can then be moved to any instance your require it on. You should not reconfigure now-cli to deploy directly to prod is my advice.

DirkRedeker
Mega Sage

Hi Tommy

Thanks for your comment. I have not tried yet if I also can transfer by "XML" export/import of the affected tables, which you can find in the update set for your scope/project:

> System Update Sets > Local Update Set

find_real_file.png

Do you have any experience on that?

BR

Dirk

Tommy Jensen
Mega Guru

I am not sure I understand 100%. But if you mean export of the updateset as xml then yes you can do that when the updateset is completed. Alltough I have not done this specifically on a custom component but I fully export it to work exactly like any othe r updatesets which I have exported many times to load elsewhere.

DirkRedeker
Mega Sage

Yes, I meant specifically, if you tried with a custom NOW UI Component. I think it should work, but I have not tried yet.

BR

Dirk

Matt Hernandez
Tera Guru

Well I deployed this component at the point where you wrote, "Whoa, what a ride" and after adding it to an existing page I got an error which prevents the workspace home page from displaying. 

Could not serve invalid request for UX Page, sys_id: b70867ad0f603300bb57f4a1ff767e15

The sys_id is that of 'Workspace Core' UX page. My component is identical with yours at that point in the article except for the scope difference. I'm not sure why putting my component on the page breaks it but I'll have to try to solve it later, I'm currently busy at work. It works locally, but I suspect possibly there is something with dependencies that I messed up.

Thanks for such a detailed article. Incredibly well done.

My specs are:

npm is 6.14.8

now-cli is 18.0.0

my pdi is Paris P1HF3, upgraded from NY.

Matt Hernandez
Tera Guru

Okay I got it. Maybe I should know this but I'm not very familiar with workspace/landing pages. The key was I could not put this component on an existing landing page, I had to associate it to the one that was deployed with it. When I re-examined the output of the deploy and I noticed a "macroponent" sys_id was generated. After failing to display my comp. on an existing landing page I had tried making a custom landing page, and I remembered wondering what to select for macroponent. I ended up copying and trying a blank landing page template but that still failed.

find_real_file.png

But since I noticed a macroponent in the deploy output messages, I went to that table and sure enough, there was one generated matching the name of my component 

find_real_file.png

So then I went back to my Landing page and selected that one for its macroponent, and that fixed it. 

find_real_file.png

 

Long6
Giga Contributor

How can I maintain a component if it was created by another one?

Tommy Jensen
Mega Guru

You need the source code from the other developer, without you are out of luck and cannot change anything.

This is why it is so important to store the source code in a repository like Github, Gitlab or similar so multiple developers can contribute.

DirkRedeker
Mega Sage

Hi

Thanks, Tommy, you are absolutely right.

You can leverage other's components, which means you can use them if they are already installed in your instance. But to change the "code", you need to get back to the author. You will not find the source code for it in ServiceNow.

BR

Dirk

Foster Hardie
Tera Expert

I've been playing with this against a personal dev instance (PDI) and am wondering about how best to move to our corporate instances. I suspect I'll have the best luck, given scope names, if I start over with a new project build and just bring my source code into that project. Any thoughts or guidance here from others?

FYI (and I'd think many would be in this boat) our corp instances are Orlando at the moment, but I'm developing for Paris. This is going to be an ongoing maintenance concern as the UI Framework is destined to rapidly change between versions, and we'll want to dev on v-next while it evolves. It's not clear to me if there is any easy way to manage this other than ripping and gripping fresh project builds and moving code around.

I wonder, also, if upgrades will be similarly messy until the tooling matures.

DirkRedeker
Mega Sage

Hi

Thanks a lot for your feedback and contribution.

I have not done this so far, because I do not feel like using the NOW UI Experience in PROD right now. I mean, it is definitively NOT beta, but there seems to be so much coming up in Quebeck so that I am now just on the "preparation phase" 🙂

Anyhow, I would NOT suggest developing on a release different from what you have in PROD.

I always would recommend developing on ORLANDO, when your PROD is ORLANDO - even further, use the same patch level.

There is only ONE exception for me:

When you want to UPGRADE to v-next, you can prepare on DEV and then do the needed steps to roll out (on the upgraded PROD).

If I find out some news, on how to deploy the Components in the "best way", I will come back to create a new article on that.

Thanks for your participation!

BR

Dirk

Tommy Jensen
Mega Guru

Reg Quebec. I am also in waiting mode right now because there are major news/changes coming in Quebec. For me Quebec will probably change what kind of components I want to build going forward.

Foster Hardie
Tera Expert

We'll see how the tooling evolves. I suspect version management and upgrades are going to be a major pain point. Nonetheless, I'm putting a toe in the water with Paris to gain a fuller understanding of how to maintain custom workspace UI.

Thanks for this excellent article.

 

Jagadeesh R
Kilo Explorer

Hi All,

      Did any one able to get the now cli component installed for quebec release?

Thanks,

Jagadeesh

Willingham32
Kilo Explorer

This is a very informative blog for me. I am very much benefited after reading this blog. Keep sharing.

My Ground Biz

Jenkins56
Kilo Explorer

A very awesome blog post. We are really grateful for your blog post. You will find a lot of approaches after visiting your post. I was exactly searching for.Thanks for such post and please keep it up.

mcdvoice

Schmeler
Kilo Explorer

I don't know what the real topic is all about but it seems to be some building that you can see here and maybe would like to know this now as read more info will help you in knowing about stuff that was always there for us to go for a better enough reason later.

Ran6
Tera Contributor

hello, i am adding the component as related item in agent workspace to incident table, so when i enter an incident record, i can see the component in a new tab.

how i can pass values (number, caller_id, etc) from the incident record to the component?

Version history
Last update:
‎09-27-2020 10:21 PM
Updated by: