<h2>Developing custom widgets</h2><br/><div style="overflow-x:auto"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta content="text/html; charset=UTF-8" /><meta name="copyright" content="(C) Copyright 2025" /><meta name="DC.rights.owner" content="(C) Copyright 2025" /><meta name="generator" content="DITA-OT" /><meta name="DC.type" content="concept" /><meta name="DC.title" content="Developing custom widgets" /><meta name="abstract" content="Develop custom widgets for portals using AngularJS, Bootstrap, and the ServiceNow API." /><meta name="description" content="Develop custom widgets for portals using AngularJS, Bootstrap, and the ServiceNow API." /><meta name="DC.subject" content="widget developer guide, develop widgets in the Service Portal, Service Portal widgets" /><meta name="keywords" content="widget developer guide, develop widgets in the Service Portal, Service Portal widgets" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/c_ServicePortal.html" /><meta name="DC.relation" scheme="URI" content="../../../administer/navigation-and-ui/concept/c_NavigationAndTheUserInterface.html" /><meta name="DC.relation" scheme="URI" content="../../../administer/general/concept/configure-uis-and-portals.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/widget-best-practices.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/adv-widget-tutorial.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/task/t_CloneAndEditAWidget.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/task/create-new-widget.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/c_WidgetInstanceOptions.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/reference/widget-api-reference.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/task/angular-providers.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/c_NestedWidgets.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/task/widget-dependencies.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/c_WidgetLocalization.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/task/ui-macro-widget.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/reference/widget-troubleshooting-guide.html" /><meta name="DC.relation" scheme="URI" content="../../../build/service-portal/concept/sp-diagnostic-tool.html" /><meta name="DC.creator" content="ServiceNow" /><meta name="DC.date.created" content="2023-08-03" /><meta name="DC.date.modified" content="2024-02-01" /><meta name="mini-toc" content="yes" /><meta name="DC.format" content="XHTML" /><meta name="DC.identifier" content="widget-dev-guide" /><link rel="stylesheet" type="text/css" href="../../../CSS/commonltr.css" /><title>Developing custom widgets</title></head><body id="widget-dev-guide"> <div class="breadcrumb"><a class="link" href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/administer/navigation-and-ui/concept/c_NavigationAndTheUserInterface.html" title="Interact with ServiceNow AI Platform applications and data in the way that works best for you.">Configure user experiences</a> > <a class="link" href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/administer/general/concept/configure-uis-and-portals.html" title="Customize your interface to create an efficient, unique experience for users and customers.">Configure UIs and portals</a> > </div> <h1 class="title topictitle1" id="ariaid-title1">Developing custom widgets</h1> <div class="body conbody"><p class="shortdesc">Develop custom widgets for portals using AngularJS, Bootstrap, and the <span class="ph">ServiceNow</span> API.</p> <div class="section" id="widget-dev-guide__section_xrx_qf2_kz"><h2 class="title sectiontitle">Before you begin</h2> <div class="p">To develop widgets, you need <span class="ph">ServiceNow</span> API experience to: <ul class="ul" id="widget-dev-guide__ul_bs4_rch_j1b"><li class="li">Run record queries on the server.</li><li class="li">Create and update records.</li></ul> </div> <div class="p">You need AngularJS experience to: <ul class="ul" id="widget-dev-guide__ul_hmf_5ch_j1b"><li class="li">Bind variables to client controllers.</li><li class="li">Access server objects in a widget.</li><li class="li">Gather user input.</li></ul> </div> <p class="p">Optionally, you can build on the Bootstrap template by accessing Bootstrap components.</p> </div> <div class="section" id="widget-dev-guide__section_gpd_lkw_h1b"><h2 class="title sectiontitle">Parts of a widget</h2> <p class="p">Like Angular directives, widgets execute a specified behavior within a <span class="ph">Service Portal</span> page. A widget includes mandatory and optional scripting components.</p> <div class="p"><dl class="dl"> <dt class="dt dlterm" id="widget-dev-guide__widget-html-template">HTML template</dt> <dd class="dd"> <p class="p">A mandatory widget component.</p> <p class="p">The HTML template requires knowledge of AngularJS to display and gather data. Use the HTML template to:</p> <div class="p"> <ul class="ul" id="widget-dev-guide__ul_chb_mdh_j1b"><li class="li">Render the dynamic view that a user sees in the browser using information from the model and controller.</li><li class="li">Bind client script variables to your markup.</li><li class="li">Gather data from the end user.</li></ul> </div> </dd> <dt class="dt dlterm" id="widget-dev-guide__widget-client-script">Client script</dt> <dd class="dd"> <p class="p">A mandatory widget component.</p> <p class="p">A client script requires knowledge of both the <span class="ph">ServiceNow</span> API and AngularJS to create a client controller. Use the client script to:</p> <div class="p"> <ul class="ul" id="widget-dev-guide__ul_elh_d2h_j1b"><li class="li">Map server data from JavaScript and JSON objects to client objects.</li><li class="li">Process data before rendering it.</li><li class="li">Pass data to the HTML template.</li><li class="li">Pass user input and data back to the server for processing.</li></ul> </div> </dd> <dt class="dt dlterm" id="widget-dev-guide__widget-server-script">Server script</dt> <dd class="dd"> <p class="p">A mandatory widget component.</p> <p class="p">A server script requires knowledge of the <span class="ph">ServiceNow</span> API to work with record data. Use the server script to:</p> <div class="p"> <ul class="ul" id="widget-dev-guide__ul_n5p_42h_j1b"><li class="li">Set the initial state of the widget.</li><li class="li">Send record data to the widget client script using the <span class="ph uicontrol">data</span> variable.</li><li class="li">Run server-side queries.</li></ul> </div> </dd> <dt class="dt dlterm" id="widget-dev-guide__widget-link">Link function</dt> <dd class="dd"> <p class="p">An optional widget component.</p> <p class="p">The link function requires knowledge of AngularJS. Use a link function to directly manipulate the DOM.</p> </dd> <dt class="dt dlterm" id="widget-dev-guide__widget-option-schema">Option schema</dt> <dd class="dd"> <p class="p">An optional widget component.</p> <p class="p">Allows a <span class="ph">Service Portal</span> admin to configure a widget. Use the option schema to:</p> <div class="p"> <ul class="ul" id="widget-dev-guide__ul_cmx_w3h_j1b"><li class="li">Specify the parameters for a widget.</li><li class="li">Allow admin users to define instance options for a widget instance.</li><li class="li">Develop flexible, reusable widgets.</li></ul> </div> </dd> <dt class="dt dlterm">Angular Providers</dt> <dd class="dd"><p class="p">An optional widget component.</p> <p class="p">Angular Providers require knowledge of AngularJS. Use Angular Providers to:</p> <div class="p"><ul class="ul" id="widget-dev-guide__ul_mm2_2zq_yz"><li class="li">Keep widgets in sync when changing records or filters.</li><li class="li">Share context between widgets.</li><li class="li">Maintain and persist state.</li><li class="li">Create reusable behaviors and UI components and inject them into multiple widgets.</li></ul> </div> </dd> <dt class="dt dlterm">Dependencies</dt> <dd class="dd"><p class="p">An optional widget component.</p> <p class="p">A widget dependency is an external resource used by your widget such as JavaScript or CSS files.</p> </dd> </dl> </div> </div> <div class="section" id="widget-dev-guide__section_rsq_g1h_j1b"><h2 class="title sectiontitle">Global objects in widgets</h2> <p class="p">When a widget begins to render for the first time on a page, the server script executes first and accesses three global objects: <span class="ph uicontrol">input</span>, <span class="ph uicontrol">options</span>, and <span class="ph uicontrol">data</span>. Because the <span class="ph uicontrol">input</span> variable is a data object sent from the client script, this variable is undefined when first initialized.</p> <p class="p"><img class="image" id="widget-dev-guide__image_bhx_lrw_xz" width="600" src="../image/Server-ClientGlobalScripts.png" alt="Available variables in server and client script global" /></p> <p class="p">When a widget is first instantiated, the server script:</p> <div class="p"><ol class="ol" id="widget-dev-guide__ol_sh3_btw_xz"><li class="li">Initializes an empty <span class="ph uicontrol">data</span> object.</li><li class="li">Initializes the <span class="ph uicontrol">input</span> object with any data sent from the client controller, or the <span class="ph uicontrol">options</span> object with any data used to initialize the widget.</li><li class="li">Sends the <span class="ph uicontrol">data</span> object to the client controller as JSON.</li></ol> </div> <p class="p">The client script:</p> <div class="p"><ol class="ol" id="widget-dev-guide__ol_mjs_jtw_xz"><li class="li"><p class="p">Accesses the server <span class="ph uicontrol">data</span> object using <code class="ph codeph">c.data</code>.</p> <div class="p"><div class="note"><span class="notetitle">Note:</span> By default, widgets use the <span class="ph uicontrol">c</span> variable to represent the controller instance using <code class="ph codeph">controller as</code> syntax. You can change this variable when creating or cloning widgets.</div> </div> </li><li class="li"><p class="p">Uses <code class="ph codeph">server.update()</code> to post changes to the data model. This method updates the server script using the <span class="ph uicontrol">input</span> object.</p> <div class="p"><div class="note"><span class="notetitle">Note:</span> After calling <code class="ph codeph">server.update()</code>, the client script <span class="ph uicontrol">data</span> object is automatically overwritten by the server script <span class="ph uicontrol">data</span> object.</div> </div> </li><li class="li">Uses <code class="ph codeph">c.options</code> to access the values used to invoke the widget on the server. This object is read-only.</li></ol> </div> </div> <div class="section" id="widget-dev-guide__section_dsy_kch_j1b"><h2 class="title sectiontitle">Using the Widget Editor</h2> <p class="p">When you create a widget, a record is created in the sp_widget table. However, you can use the Widget Editor in <span class="ph">Service Portal</span> Configuration as your scripting environment. The Widget Editor is a full page application similar to an IDE. You can show the parts of the widget you want to edit and hide the rest, while previewing your changes in real time.</p> <p class="p"><img class="image" id="widget-dev-guide__image_eyj_bt3_yv" width="600" src="../image/WidgetEditorSample.png" alt="Widget editor with the calculator widget showing script examples for the HTML template, CSS, Client script, and the server script" /></p> </div> </div> <div class="related-links"> <ul class="ullinks"><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/widget-best-practices.html">Recommendations for developing widgets</a></strong><br /> When developing custom widgets, keep these recommendations in mind for optimal performance, scalable development, and a good user experience.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/adv-widget-tutorial.html">Tutorial: Build a custom widget</a></strong><br /> Follow this tutorial to build a custom widget that displays <span class="ph">Service Catalog</span> items. Use this tutorial as a model to help you understand the advanced scripting power of the <span class="ph">Service Portal</span>.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/task/t_CloneAndEditAWidget.html">Clone a widget</a></strong><br /> Take advantage of existing code by cloning and editing an existing widget.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/task/create-new-widget.html">Create a new widget</a></strong><br /> Create a new widget to build a custom widget from scratch.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/c_WidgetInstanceOptions.html">Widget option schema</a></strong><br /> Widget instances allow users to uniquely configure each widget they add to a page. Use the option schema to define the parameters for your widget.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/reference/widget-api-reference.html">Widget API reference</a></strong><br /> <span class="ph">Service Portal</span> includes client and server side APIs to use in widget client and server scripts.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/task/angular-providers.html">Reuse components with Angular Providers</a></strong><br /> Angular Providers are reusable components that can be injected into multiple widgets. To ensure quick loading widgets and a high performing portal, create Angular Providers instead of overloading your client controllers with persistent data and additional logic. With Angular Providers, you can maintain data for the lifetime of your <span class="ph">Service Portal</span> and reuse components and data objects across multiple widgets.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/c_NestedWidgets.html">Embedded widgets</a></strong><br /> Embed a widget in the HTML template, server script, or client script.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/task/widget-dependencies.html">Create a widget dependency</a></strong><br /> In Service Portal, you can link JavaScript and CSS files to widgets to create dependencies between widgets and third-party libraries, external style sheets, and angular modules.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/c_WidgetLocalization.html">Internationalize a widget</a></strong><br /> Use the <code class="ph codeph">${}</code> or <code class="ph codeph">gs.getMessage()</code> syntax in the <span class="ph uicontrol">HTML Template</span>, <span class="ph uicontrol">Client Script</span>, or <span class="ph uicontrol">Server Script</span> fields of a widget to tag strings for translation so you can localize your <span class="ph">Service Portal</span> content.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/task/ui-macro-widget.html">Replace a Service Catalog form script with a widget</a></strong><br /> You can use widgets in <span class="ph">Service Portal</span> to replace UI Macros. If your <span class="ph">Service Catalog</span> form includes a UI Macro that references other fields or variables on the form, you can create a widget to hold reusable code and embed it within the <span class="ph">Service Catalog</span> form. Use special syntax to access any variable fields on the form.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/reference/widget-troubleshooting-guide.html">Widget troubleshooting guide</a></strong><br /> Use the following tools to investigate and resolve unexpected behavior in your custom <span class="ph">Service Portal</span> widgets.</li><li class="link ulchildlink"><strong><a href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/sp-diagnostic-tool.html">Widget diagnostics</a></strong><br /> <span class="ph">Resolve <span class="ph">Service Portal</span> page issues by identifying widget customization levels and checking widget code directly from a portal page.</span></li></ul> <div class="familylinks"> <div class="parentlink"><strong>Parent Topic:</strong> <a class="link" href="https://docs.servicenow.com/bundle/washingtondc-platform-user-interface/page/build/service-portal/concept/c_ServicePortal.html" title="Service Portal allows you to build a mobile-friendly self-service portal experience for your employees or customers. Service Portal is a ServiceNow AI Platform feature that is active by default and interacts with parts of the platform so users can access platform features through portals.">Service Portal</a></div> </div> </div></body></html></div>