{"id":75291,"date":"2017-02-06T05:00:17","date_gmt":"2017-02-06T05:00:17","guid":{"rendered":"http:\/\/www.esri.com\/arcgis-blog\/products\/product\/uncategorized\/enliven-your-web-apps-with-custom-actions\/"},"modified":"2018-05-11T18:13:07","modified_gmt":"2018-05-11T18:13:07","slug":"enliven-your-web-apps-with-custom-actions","status":"publish","type":"blog","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions","title":{"rendered":"Enliven your web apps with custom actions"},"author":6561,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"_acf_changed":false,"_searchwp_excluded":""},"categories":[22941],"tags":[24921,27491,28061,31291,26521,27731],"industry":[],"product":[36831,36601],"class_list":["post-75291","blog","type-blog","status-publish","format-standard","hentry","category-mapping","tag-javascript","tag-jsapi4","tag-pop-ups","tag-renderers","tag-visualization","tag-widgets","product-js-api-arcgis","product-developers"],"acf":{"short_description":"The 4.x series of the ArcGIS API for JavaScript introduced the concept of actions. An action is a task that can be triggered by a user by...","flexible_content":[{"acf_fc_layout":"content","content":"<p>The <a href=\"https:\/\/developers.arcgis.com\/javascript\/\">4.x series of the ArcGIS API for JavaScript<\/a> introduced the concept of <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-support-Action.html\"><strong>actions<\/strong><\/a>. An action is a task that can be triggered by a user by clicking its simple button interface. For example, clicking the magnifying glass button on the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-widgets-Popup.html\">Popup<\/a> widget triggers the <code>zoom-in<\/code> action. <\/p>\n<p><a href=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/popup-actions.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/popup-actions.png\" alt=\"\" width=\"373\" height=\"221\" class=\"alignnone size-full wp-image-73803\" \/><\/a><\/p>\n<p>Actions provide a straightforward workflow for adding custom behavior to web apps and provide a simple UI for users to execute them. Developers can enhance their applications by allowing users to call custom functions through <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-support-Action.html\">Actions<\/a>. Actions are supported in both the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-widgets-LayerList.html\">LayerList<\/a> or <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-widgets-Popup.html\">Popup<\/a> widgets. By default the popup has a zoom-in action that allows users to zoom in to the selected feature. <\/p>\n<p><a href=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/popup-zoom-action.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/popup-zoom-action.gif\" alt=\"\" width=\"480\" height=\"280\" class=\"alignnone size-full wp-image-73804 noIMGBackground\" \/><\/a><\/p>\n<p>While the LayerList widget does not come equipped default actions, developers can add actions on a layer-by-layer basis. For example, you can provide an action that allows users to change the opacity of specific layers.<\/p>\n<p><a href=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/layerlist-opacity-action.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/layerlist-opacity-action.gif\" alt=\"\" width=\"480\" height=\"266\" class=\"alignnone size-full wp-image-73807 noIMGBackground\" \/><\/a><\/p>\n<p>The following samples in the ArcGIS API for JavaScript documentation demonstrate how developers can create custom actions in these widgets:<\/p>\n<ul>\n<li><a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/popup-actions\/index.html\">Define custom popup actions<\/a> &#8211; adds an action to a popup that calculates the length of the selected feature and displays it in the popup.<\/li>\n<li><a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/popup-custom-action\/index.html\">Custom popup actions per feature<\/a> &#8211; adds an action to a popup that defines custom behavior for opening a new web page based on an attribute of the selected feature.<\/li>\n<li>\n<a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/scene-local\/index.html\">Create a local scene<\/a> &#8211; Adds an action to a popup that buffers the selected point and displays the number of features from another layer that intersect that buffer.<\/li>\n<li><a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/widgets-layerlist-actions\/index.html\">LayerList widget with actions<\/a> &#8211; adds multiple actions to a LayerList widget that allow the user to view service information for the given layer, zoom to the full extent of the layer, and change the opacity of the layer.<\/li>\n<\/ul>\n<h1>Adding actions to the LayerList widget<\/h1>\n<p>LayerList actions are associated with specific layers in the widget. The <a href=\"http:\/\/ekenes.github.io\/esri-js-samples\/4\/widgets\/layerlist-actions-renderers\/\">following sample<\/a> provides another example of how LayerList actions can be used. Prior to creating this sample, I enriched a layer of municipal boundaries in Mexico with education and population attributes. I then added this layer to <a href=\"https:\/\/www.arcgis.com\/home\/index.html\">ArcGIS Online<\/a> and copied it twelve times, assigning different renderers to each copy of the layer. Because I found these various visualizations interesting I decided to create an app that allows users to easily toggle these visualizations on the same layer without loading 12 separate layers of the same data and thus unnecessarily querying duplicate data. <\/p>\n<p><a href=\"http:\/\/ekenes.github.io\/esri-js-samples\/4\/widgets\/layerlist-actions-renderers\/\">View Live Sample<\/a><span style=\"padding-right:50px\"><\/span><a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/4\/widgets\/layerlist-actions-renderers\/index.html\">View Code<\/a><br \/>\n<a href=\"http:\/\/ekenes.github.io\/esri-js-samples\/4\/widgets\/layerlist-actions-renderers\/\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/predominance.png\" alt=\"\" width=\"1425\" height=\"841\" class=\"alignnone size-full wp-image-73805 noIMGBackground\" \/><\/a><\/p>\n<p>To create this &#8220;renderer list&#8221; functionality, I added the LayerList widget to the sample, saved all twelve renderers to an object after loading the web map and removed all layers except for one before adding the map to the view. I then created a separate action for each renderer in the LayerList widget that allows the user to toggle the visualization of the single layer.<\/p>\n<h1>Create actions in two easy steps<\/h1>\n<p>You can create custom actions in two easy steps: 1.) configuring the title and icon\/image to click, and 2.) Defining the custom behavior with function(s) executed in the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-widgets-LayerList.html#event:trigger-action\">trigger-action<\/a> event listener. The Popup and LayerList widgets both require these steps.<\/p>\n<h2>1. Configure the title and icon\/image<\/h2>\n<p>While the overall principles are the same, setting up actions in the LayerList widget are slightly different from doing so in a Popup or PopupTemplate. In LayerList, actions are created via a function you must pass to the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-widgets-LayerList.html#createActionsFunction\">createActionsFunction<\/a> property. In the sample above where 12 actions are added to the LayerList, I pass the following function to create these actions:<\/p>\n<pre><code><span><span style=\"color: #333;font-weight: bold\">function<\/span> <span style=\"color: #900;font-weight: bold\">createLayerListActions<\/span>(<span>evt<\/span>)<\/span>{\r\n  <span style=\"color: #333;font-weight: bold\">if<\/span>(evt.item.title = map.portalItem.title){\r\n    <span style=\"color: #333;font-weight: bold\">return<\/span> [ rendererInfos.map(<span><span style=\"color: #333;font-weight: bold\">function<\/span>(<span>rendererInfo<\/span>)<\/span>{\r\n      <span style=\"color: #333;font-weight: bold\">return<\/span> {\r\n        title: rendererInfo.title,\r\n        className: <span style=\"color: #d14\">\"esri-icon-maps\"<\/span>,\r\n        id: <span style=\"color: #d14\">\"change-renderer\"<\/span>\r\n      };\r\n    }) ];\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>This function has an event parameter <code>evt<\/code> that contains select properties related to the layer, such as the layer&#8217;s title. Since these actions only pertain to the layer kept from the web map, we only want the logic of the function to apply to that layer.<\/p>\n<p>Once we verify the proper layer is referenced, we&#8217;ll return a two-dimensional array of action objects. In this case, we want one action for each rendererInfo object. So I call <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-core-Collection.html#map\">map<\/a> on the collection of rendererInfos to return an action object for each renderer. The title of each action uniquely pertains to a corresponding renderer. The className and id properties assign the same icon and ids to each action so we know they refer to changing the layer&#8217;s renderer. <\/p>\n<blockquote>\n<h3><strong>Why a two-dimensional array?<\/strong><\/h3>\n<p>The array of action objects is two-dimensional to allow actions to be organized into groups. I <a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/4\/widgets\/layerlist-actions-renderers-opacity\/index.html\">modified this sample<\/a> and added a toggle-opacity action associated with only the renderers that had an opacity visual variable to demonstrate how to set up this grouping. This allows the user to better understand regions where color may be washed out because of opacity. <\/p>\n<p>In the UI, the actions are divided by breaking lines, which pair the <code>toggle-opacity<\/code> action with pertinent <code>change-renderer<\/code> actions.<\/p>\n<p><a href=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/action-toggle.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2017\/02\/action-toggle.png\" alt=\"\" width=\"287\" height=\"185\" class=\"alignnone size-full wp-image-73802\" \/><\/a><\/p>\n<p>The modified <code>createLayerListActions<\/code> function now checks if the renderer contains a visual variable. If it does, then it is pushed as a separate element in the actions array.<\/p>\n<pre><code><span><span style=\"color: #333;font-weight: bold\">function<\/span> <span style=\"color: #900;font-weight: bold\">createLayerListActions<\/span>(<span>evt<\/span>)<\/span>{\r\n  <span style=\"color: #333;font-weight: bold\">if<\/span>(evt.item.title = map.portalItem.title){\r\n\r\n    <span style=\"color: #333;font-weight: bold\">return<\/span> rendererInfos.map(<span><span style=\"color: #333;font-weight: bold\">function<\/span>(<span>rendererInfo<\/span>)<\/span>{\r\n      <span style=\"color: #333;font-weight: bold\">var<\/span> actions = [];\r\n\r\n      actions.push({\r\n        title: rendererInfo.title,\r\n        className: <span style=\"color: #d14\">\"esri-icon-maps\"<\/span>,\r\n        id: <span style=\"color: #d14\">\"change-renderer\"<\/span>,\r\n        rendererTitle: rendererInfo.title\r\n      });\r\n\r\n      <span style=\"color: #333;font-weight: bold\">var<\/span> renderer = rendererInfo.renderer;\r\n      <span style=\"color: #333;font-weight: bold\">var<\/span> hasOpacityVV = renderer &amp;&amp; renderer.visualVariables.some(<span><span style=\"color: #333;font-weight: bold\">function<\/span>(<span>variable<\/span>)<\/span>{\r\n        <span style=\"color: #333;font-weight: bold\">return<\/span> variable.type === <span style=\"color: #d14\">\"opacity\"<\/span>;\r\n      });\r\n\r\n      <span style=\"color: #333;font-weight: bold\">if<\/span> (hasOpacityVV){\r\n        actions.push({\r\n          title: <span style=\"color: #d14\">\"Toggle opacity\"<\/span>,\r\n          className: <span style=\"color: #d14\">\"esri-icon-environment-settings\"<\/span>,\r\n          id: <span style=\"color: #d14\">\"toggle-opacity\"<\/span>,\r\n          rendererTitle: rendererInfo.title\r\n        });\r\n      }\r\n      <span style=\"color: #333;font-weight: bold\">return<\/span> actions;\r\n    });\r\n\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>See the full <a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/4\/widgets\/layerlist-actions-renderers-opacity\/index.html\">code<\/a> and view the updated <a href=\"http:\/\/ekenes.github.io\/esri-js-samples\/4\/widgets\/layerlist-actions-renderers-opacity\/\">app live<\/a>.\n<\/p><\/blockquote>\n<h2>2. Define the custom behavior<\/h2>\n<p>The next step is to define the custom behavior to execute when the trigger-action event fires. In this case, I wrote a function called <code>toggleRenderer()<\/code> that will fire each time an action is clicked.<\/p>\n<pre><code><span><span style=\"color: #333;font-weight: bold\">function<\/span> <span style=\"color: #900;font-weight: bold\">toggleRenderer<\/span>(<span>evt<\/span>)<\/span>{\r\n  <span style=\"color: #333;font-weight: bold\">if<\/span>(evt.action.id === <span style=\"color: #d14\">\"change-renderer\"<\/span>){\r\n    <span style=\"color: #333;font-weight: bold\">var<\/span> matchingInfo = rendererInfos.find(<span><span style=\"color: #333;font-weight: bold\">function<\/span>(<span>info<\/span>)<\/span>{\r\n      <span style=\"color: #333;font-weight: bold\">return<\/span> info.title === evt.action.title;\r\n    });\r\n    <span style=\"color: #333;font-weight: bold\">var<\/span> renderer = matchingInfo.renderer.clone();\r\n    <span style=\"color: #333;font-weight: bold\">var<\/span> layer = view.map.layers.getItemAt(<span style=\"color: #008080\">0<\/span>);\r\n    layer.renderer = renderer;\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>That function is then set as the callback to the <code>trigger-action<\/code> event on the widget.<\/p>\n<pre><code>layerList.on(<span style=\"color: #d14\">\"trigger-action\"<\/span>, toggleRenderer);\r\n<\/code><\/pre>\n<p>Fundamentally, the logic is straightforward. First, we check to see if the action id matches the change-renderer id I assigned to each action. Then we find the renderer info that matches the title of the action that was clicked. The renderer associated with that info object is then applied to the layer.<\/p>\n<p>Now we have a simple app that allows users to choose from multiple renderers and apply them to a single layer. <\/p>\n<h1>Conclusion<\/h1>\n<p>Actions provide a straightforward workflow for applying custom behavior to an app within a simple UI. This behavior can either be simple or more complex to provide users with a richer experience to explore and analyze geospatial data in web apps. So <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/sandbox\/index.html?sample=widgets-layerlist-actions\">try it out<\/a>! Be creative. Define your own actions and explore how you can apply them in your own apps.<\/p>\n"}],"authors":[{"ID":6561,"user_firstname":"Kristian","user_lastname":"Ekenes","nickname":"Kristian Ekenes","user_nicename":"kekenes","display_name":"Kristian Ekenes","user_email":"KEkenes@esri.com","user_url":"https:\/\/github.com\/ekenes","user_registered":"2018-03-02 00:18:32","user_description":"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.","user_avatar":"<img data-del=\"avatar\" src='https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png' class='avatar pp-user-avatar avatar-96 photo ' height='96' width='96'\/>"}],"related_articles":"","card_image":false,"wide_image":false},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Enliven your web apps with custom actions<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Enliven your web apps with custom actions\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\" \/>\n<meta property=\"og:site_name\" content=\"ArcGIS Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/esrigis\/\" \/>\n<meta property=\"article:modified_time\" content=\"2018-05-11T18:13:07+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@ESRI\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\"},\"author\":{\"name\":\"Kristian Ekenes\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b\"},\"headline\":\"Enliven your web apps with custom actions\",\"datePublished\":\"2017-02-06T05:00:17+00:00\",\"dateModified\":\"2018-05-11T18:13:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\"},\"wordCount\":7,\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"keywords\":[\"JavaScript\",\"jsapi4\",\"pop-ups\",\"renderers\",\"Visualization\",\"widgets\"],\"articleSection\":[\"Mapping\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\",\"name\":\"Enliven your web apps with custom actions\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\"},\"datePublished\":\"2017-02-06T05:00:17+00:00\",\"dateModified\":\"2018-05-11T18:13:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.esri.com\/arcgis-blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Enliven your web apps with custom actions\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"name\":\"ArcGIS Blog\",\"description\":\"Get insider info from Esri product teams\",\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\",\"name\":\"Esri\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"contentUrl\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"width\":400,\"height\":400,\"caption\":\"Esri\"},\"image\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/esrigis\/\",\"https:\/\/x.com\/ESRI\",\"https:\/\/www.linkedin.com\/company\/5311\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b\",\"name\":\"Kristian Ekenes\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png\",\"contentUrl\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png\",\"caption\":\"Kristian Ekenes\"},\"description\":\"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.\",\"sameAs\":[\"https:\/\/github.com\/ekenes\",\"https:\/\/www.linkedin.com\/in\/kristian-ekenes\/\",\"https:\/\/x.com\/kekenes\"],\"gender\":\"male\",\"jobTitle\":\"Principal Product Engineer\",\"worksFor\":\"Esri\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Enliven your web apps with custom actions","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions","og_locale":"en_US","og_type":"article","og_title":"Enliven your web apps with custom actions","og_url":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions","og_site_name":"ArcGIS Blog","article_publisher":"https:\/\/www.facebook.com\/esrigis\/","article_modified_time":"2018-05-11T18:13:07+00:00","twitter_card":"summary_large_image","twitter_site":"@ESRI","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#article","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions"},"author":{"name":"Kristian Ekenes","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b"},"headline":"Enliven your web apps with custom actions","datePublished":"2017-02-06T05:00:17+00:00","dateModified":"2018-05-11T18:13:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions"},"wordCount":7,"publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"keywords":["JavaScript","jsapi4","pop-ups","renderers","Visualization","widgets"],"articleSection":["Mapping"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions","url":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions","name":"Enliven your web apps with custom actions","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#website"},"datePublished":"2017-02-06T05:00:17+00:00","dateModified":"2018-05-11T18:13:07+00:00","breadcrumb":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/mapping\/mapping\/enliven-your-web-apps-with-custom-actions#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.esri.com\/arcgis-blog\/"},{"@type":"ListItem","position":2,"name":"Enliven your web apps with custom actions"}]},{"@type":"WebSite","@id":"https:\/\/www.esri.com\/arcgis-blog\/#website","url":"https:\/\/www.esri.com\/arcgis-blog\/","name":"ArcGIS Blog","description":"Get insider info from Esri product teams","publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization","name":"Esri","url":"https:\/\/www.esri.com\/arcgis-blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","contentUrl":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","width":400,"height":400,"caption":"Esri"},"image":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/esrigis\/","https:\/\/x.com\/ESRI","https:\/\/www.linkedin.com\/company\/5311\/"]},{"@type":"Person","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b","name":"Kristian Ekenes","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/","url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png","contentUrl":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png","caption":"Kristian Ekenes"},"description":"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.","sameAs":["https:\/\/github.com\/ekenes","https:\/\/www.linkedin.com\/in\/kristian-ekenes\/","https:\/\/x.com\/kekenes"],"gender":"male","jobTitle":"Principal Product Engineer","worksFor":"Esri","url":"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes"}]}},"text_date":"February 6, 2017","author_name":"Kristian Ekenes","author_page":"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes","custom_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2025\/08\/Newsroom-Keyart-Wide-1920-x-1080.jpg","primary_product":"ArcGIS Maps SDK for JavaScript","tag_data":[{"term_id":24921,"name":"JavaScript","slug":"javascript","term_group":0,"term_taxonomy_id":24921,"taxonomy":"post_tag","description":"","parent":0,"count":151,"filter":"raw"},{"term_id":27491,"name":"jsapi4","slug":"jsapi4","term_group":0,"term_taxonomy_id":27491,"taxonomy":"post_tag","description":"","parent":0,"count":111,"filter":"raw"},{"term_id":28061,"name":"pop-ups","slug":"pop-ups","term_group":0,"term_taxonomy_id":28061,"taxonomy":"post_tag","description":"","parent":0,"count":39,"filter":"raw"},{"term_id":31291,"name":"renderers","slug":"renderers","term_group":0,"term_taxonomy_id":31291,"taxonomy":"post_tag","description":"","parent":0,"count":9,"filter":"raw"},{"term_id":26521,"name":"Visualization","slug":"visualization","term_group":0,"term_taxonomy_id":26521,"taxonomy":"post_tag","description":"","parent":0,"count":45,"filter":"raw"},{"term_id":27731,"name":"widgets","slug":"widgets","term_group":0,"term_taxonomy_id":27731,"taxonomy":"post_tag","description":"","parent":0,"count":20,"filter":"raw"}],"category_data":[{"term_id":22941,"name":"Mapping","slug":"mapping","term_group":0,"term_taxonomy_id":22941,"taxonomy":"category","description":"","parent":0,"count":2698,"filter":"raw"}],"product_data":[{"term_id":36831,"name":"ArcGIS Maps SDK for JavaScript","slug":"js-api-arcgis","term_group":0,"term_taxonomy_id":36831,"taxonomy":"product","description":"","parent":36601,"count":363,"filter":"raw"},{"term_id":36601,"name":"Developers","slug":"developers","term_group":0,"term_taxonomy_id":36601,"taxonomy":"product","description":"","parent":0,"count":765,"filter":"raw"}],"primary_product_link":"https:\/\/www.esri.com\/arcgis-blog\/?s=#&products=js-api-arcgis","_links":{"self":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/75291","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/users\/6561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/comments?post=75291"}],"version-history":[{"count":0,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/75291\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/media?parent=75291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/categories?post=75291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/tags?post=75291"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/industry?post=75291"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/product?post=75291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}