Open Site Navigation

Going further with Now Experience Components (Part 1)

Updated: Nov 12



I split this up into a multi-part series because there's a lot of main concepts I want to cover. I will not be covering much about the ServiceNow Command Line in this series outside of using it, for more information on that check out my previous post: Working Through Now Experience Components


The goal of this series is to explore the main concepts of component development in ServiceNow, and along the way build a component that can query for data and pass data. I will be following along with published resources from ServiceNow and linking helpful articles I find along the way. By no means is this an authoritative source of information, as I am learning alongside everyone else. I hope this series serves more as digest of foundational concepts/terminology and provides further learning resources. Just to note, I started writing this post on a freshly upgraded Rome PDI, and I'll be using the terms 'UI Framework' and 'Now Experience Framework' interchangeably.



Foundational Concepts


Before I jump in and start building components that are more complex than the examples for people counters, etc. i'm going to spend some time reviewing the documentation here and familiarizing myself with the concepts of components and how they work. For those who have worked on the ServiceNow platform before, and worked in things such as Service Portal, this is going to be a new direction for most of us.


I'll start with the basic building blocks of what a Web Component is in the following sections. I found a great article on the React site about Web Components and React, as I think we tend to use them interchangeably within the ServiceNow community, but they are not the same. ServiceNow is utilizing React within its UI Component Framework to manage data and the DOM, but the component itself is built using their flavor of Web Components. Having a foundational understanding of both React and Web Components is going to be needed here, but don't feel like you have to be a React pro to get started, just start looking through the pages I've linked here and documentation to learn the building blocks while you build simple components.


Custom Elements


If you've worked with HTML before, you're used to working with elements or tags such as <p> or <h1>. Previously, the elements that could be used with HTML were already defined and limited, think <div> while assigning an id or class attribute and having to work within those parameters. Web Components uses the Custom Elements API to allow developers to define and call their own HTML tags or elements within the component. This is where the ServiceNow documentation gets fuzzy on this, because they really don't speak to this concept very much, and go on the assumption you have previous Web Component knowledge or use other resources to fill in the gaps. When working with components in the UI Framework you will use the following API createCustomElement:


import {createCustomElement} from '@servicenow/ui-core';

createCustomElement('example-blog-element', {
    properties: {
        food: {
            default: 'pizza'
        }
    },
    transformState: ({properties}) => properties,
    view: ({food}) => <p>I like {food}!</p>
});

I do want to take time to mention the use of properties here, and will touch base on this in depth more later. If you think about your custom element as an object such as:


var obj = {
    food: "ice cream"
}

A property in the web component sense is a variable bound within the object, a good example is the HTML img element, which has an attribute of src so when you go to create an image in HTML you use something like:


<img src="myimage.jpg">

Behind the scenes the img element exists in the DOM such as:


var HTMLImageElement = {
    src: "myimage.jpg"
}

When you break the above example down, you're really just creating an element that looks like this in HTML:


<example-blog-element food="pizza">

The first thing we do when we jump into building components in ServiceNow is define and register our custom element and any properties we may have. This does get more complex and I will build on this more later, but for now this is a super simplified example of custom elements and properties. You may be asking from this example "I've created one custom element, do I create multiple ones within a component?'", and for now based upon the examples I've seen and my limited understanding, I believe the UI Framework is using the method of bundling custom functionality into one single tag per component rather than having multiple tags within a component. If you know any differently, please comment below as I don't want to steer folks wrong on this one. You will also notice if reading other documentation that ServiceNow has obscured a lot of the work with registering elements, and extending HTMLElement for us so that we don't have to do that every time and calling our tags in the DOM when we place a component on a page in UI Builder, etc. There's tons of articles out there about Custom Elements, I really like this one and this one as the author has some real examples of usage.


Shadow DOM


In a nutshell, Shadow DOMs allow you do whatever it is you need to do within your component without impacting other components or elements within the global DOM. Web components and the UI Framework utilize Shadow DOMs to keep component code isolated or encapsulated from one another, so things like markup and styling don't impact one another. I'm not going to get too deep into the technology here, but there is a great MDN article on Shadow DOM.


Functionality


I suggest heading over to this reference documentation on how components work as the nexts step in understanding the foundations of UI Framework. I'm not going to reiterate everything, but the basic takeaways is that components react to events. When you have this in mind and are working with data or other events within a component you must design it in a way that supports the underlying architecture of components so basically think in terms of how you want events to trigger, and that synchronous updates do not happen. I really like how ServiceNow laid it out in the article that components cannot be thought of as lines of code that execute, and to think of it as an event that has happened and how you want the component to respond to that event.


As I was reading through the documentation, something stuck out to me that I think is important to call out here, especially since most of us will be moving from Service Portal/AngularJS to Now Experience Framework:


AngularJS supported bi-directional data binding with it's MVC (Model-View-Controller) model, meaning we could manipulate server data from the view/controller and manipulate view/controller data from the server within our widgets, UI Framework components have a uni-directional MVC, meaning an action is called or dispatched from the view, the state of the component is updated, and the updated state is sent back to the view.


Breaking Down a Component


The goal of this series is to create a component that displays and interacts with data retrieved from the server, and handles actions that are performed on the presentational layer of the component. I'll also have examples of more simple components along the way to illustrate concepts, but hopefully the outcome of this series is to have a component that shows a list of records, and allows the user to click a dropdown to show different records, i.e. Incident to Problem.


I'm going to build and explain along the way, and I'm not going to dive too deep into setting up Now CLI, I have an article on that here. Note: You may need to update your ui-component extension if you're on Rome from version 19 to 20 by running: snc extension update --name ui-component


Now that I have my component project set up, I can navigate to the src > component name > index.js file within the folder I created it in and begin poking around. Again, I'm going to breeze through some of the initial setup when it comes to now-ui.json setup, but you can find out more information on the article I linked above. As a visual, here's what I have after creating a brand new project:


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

const view = (state, {updateState}) => {
    return (
        <div></div>
    );
};

createCustomElement('x-redacted-blog-dash', {
    renderer: {type: snabbdom},
    view,
    styles
});

The Developer site contains quite a bit regarding the makeup of UI Framework components. I'm going to start dissecting those sections and providing a very foundational explanation of what they are, and show some basic examples. They have some more in-depth information and examples on the site.


View


The view is what is shown on the presentational layer of the component. In the above code a variable is declared with const view. There is a lot to digest on the developer site for this topic, I'll try to touch on most of it. I do want to take a moment to discuss Snabbdom and the Virtual DOM since it relates to the view of our component.


At the top of our code we import a renderer called Snabbdom. I'll go into this just a bit, because I like context and foundational information, also here's a great blog article that sums it up better than I will. Snabbdom is basically the Virtual DOM, which is not the same as the Shadow DOM (x_x) I mentioned above. I won't get too deep here and here's another blog for you, but the Shadow DOM is the encapsulation of the implementation, or the component/custom element itself. A Virtual DOM is used in React to provide a representation of a real DOM and aids to reduce performance impacts via re-rendering the DOM. State changes are applied to the Virtual DOM, and then the DOM is updated accordingly with a group of changes, instead of re-rendering the DOM every time a state change has been made.


I feel like I've strayed a little but will try to get back on track for the view here. Within our view variable, we can pass in our properties, state, helper arguments, etc., we also define some HTML looking code, which is actually JSX which is a syntax extension to JavaScript. If you're keeping it simple a basic understanding of HTML should be fine here but of course you can go further with understanding JSX. Out of the box our JSX is <div></div>. The developer site has some great examples of dynamically rendering data within JSX by either using {} such as {state.food} or ternary operators.


Updating Components


In the UI Framework there are two ways of managing a component's information/data, either by updating properties or updating the state. I'm going to show two code examples that look basically the same to show how data can be updated by either, but will explain a little bit about when (or not) to use each one.


Properties


Since my previous code used a property, I'll start here first and show an easy example of how to get user input and update an h1 tag within the component via updating properties. In the below code, there is an input field, and a h1 tag. We pass the properties (which has a default of Pizza) and updateProperties arguments to our view and call the {food} property in the h1. Once a user enters some input into the field, we call updateProperties and use the value the user entered. I'm also going to tell you after the code snippet why you shouldn't do this.


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

const view = ({properties: {food}}, {updateProperties}) => {
   return (
      <div><span><input label="Food" messages={[]} placeholder="Enter your favorite" step="any" type="text" value="" on-input={e =>
         updateProperties({food: e.target.value})}></input></span>
      <h1>I like {food}!</h1></div>
   );
};

createCustomElement('x-redacted-blog-dash', {
   renderer: {type: snabbdom},
   view,
   styles,
   properties: {
      food: {default: 'pizza'}
   }
});

So this seems easy enough right, but I do want to mention that properties aren't really meant to be changed. They are useful if you want to set in-mutable data/default data that won't change, or pass a property from a parent to a child component, but if you're working with data inside of the component itself you should be using state instead. So really this code snippet should just be me setting the default property of Pizza and leaving it at that since I'm not passing anything from a parent component. Here's a really great article about properties versus state that will help to clear some of this up.


State


Now that we have a better understanding of properties and when to set them, let's move on to state. A component's state holds information or data about the component. Unless you set the state for the component using initialState, the component itself has no state. Let's say you won't be changing anything about your component and there won't be interaction, then you would use properties. But like our example, we will be updating information in the component, so we'd use state. I set the initialState of Pizza in the code below, but I could've left it blank and the code would read 'I like !' then I used updateState to get the value the user entered in the input, and since {food} = state, the state has been updated and the new food shows.


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

const view = (state, {updateState}) => {
   const {food} = state;
   return (
      <div><span><input label="Food" messages={[]} placeholder="Enter your favorite" step="any" type="text" value="" on-input={e =>
         updateState({food: e.target.value})}></input></span>
      <h1>I like {food}!</h1></div>
   );
};

createCustomElement('x-422452-blog-dash', {
   renderer: {type: snabbdom},
   view,
   styles,
   initialState: {
      food: 'pizza'
   }
});



To sum it up there are two types of React components, stateless and stateful. Stateless components only have properties, and properties within a component do not change. They can be set to defaults or inherited from parent components, and are great for testing the basic structure of a component because the informational should always be the same. Stateful components can contain both properties and state, and the information within them can change via updating the state. I love the quote at the bottom of this article:


"Props are a way of passing data from parent to child. State is reserved only for interactivity, that is, data that changes over time."


Wrap Up


I've covered a lot of basics in part 1, and I'm going to leave it here to marinate before proceeding any further. In speaking with the community, there's a consensus that there is a lot of concepts handed to the ServiceNow Developer community all at once with the UI Framework, and while ServiceNow has done a great job documenting their usage of Now Experience Components, it can be a bit difficult for those who may not have background knowledge of React or Web Components (i.e. me). I'll say if you are overwhelmed with Now CLI and Components, you're not alone, and that's why I decided to create this series to demystify or at least provide outside resources on Now Experience Components and the inspirations they used. Personally, I feel like the direction is going in "use the components we've provided" but the extensibility for you to create your own is there if you have the knowledge to do so, or at least this is my general feeling from the lack of documentation on getting ServiceNow developers up to speed on creating components at this current point in time. This may change with future releases and especially with trying to shift customers away from the Service Portal and AngularJS, but for now if you're on the Rome release and feel a bit lost, that's just the state of things for now. A personal opinion of mine, are that we're going to have a bit of a period of pain while ServiceNow updates its web components library to match parity to 10+ years of features they've built on the Platform UI, and some basic functionality will have to be rebuilt in custom components by the community, eventually to be replaced by an out-of-the-box component at some point down the road, but as ServiceNow developers this isn't news to us. Stay tuned for Part 2 as I begin to look more at Actions and Helpers and scaffold out the component we'll be working on to show records.



Resources


Exyte: Overview of the Web components in 2021


ServiceNow Developer Documentation: Now Experience UI Framework


ServiceNow Digital Guidebook: Getting started with the Now Experience UI Framework

413 views0 comments