<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>question Adding Custom Action Buttons to the HRM Todos Summary Widget in Community Central forum</title>
    <link>https://www.servicenow.com/community/community-central-forum/adding-custom-action-buttons-to-the-hrm-todos-summary-widget/m-p/3425939#M5403</link>
    <description>&lt;DIV class=""&gt;&lt;P&gt;Hi Community,&lt;/P&gt;&lt;P&gt;We all know that the standard Employee Center / HRSD To-do widget architecture is powerful, but it can be overwhelming to customize. The hierarchy usually looks something like this:&lt;/P&gt;&lt;P&gt;hrm-todos-summary -&amp;gt; hrm-todos-line-item -&amp;gt; task-configuration (or specific approval widgets).&lt;/P&gt;&lt;P&gt;Recently, I had a requirement to add &lt;STRONG&gt;"Request Clarification"&lt;/STRONG&gt; and &lt;STRONG&gt;"Reject with Comments"&lt;/STRONG&gt; buttons. The standard approach often involves cloning multiple child widgets or creating complex UI macros for the task configuration.&lt;/P&gt;&lt;P&gt;However, I found a cleaner way to achieve this by modifying the parent &lt;STRONG&gt;Custom HRM Todos Summary&lt;/STRONG&gt; widget directly. This keeps the logic centralized and avoids the "rabbit hole" of nested widget communication.&lt;/P&gt;&lt;P&gt;Here is how I achieved it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;The Concept&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Instead of trying to inject buttons into the child widgets, we can inject them into the ng-repeat loop of the parent widget. We use CSS to visually align them with the existing footer of the child widget, and we handle the logic (Modals + Server Updates) entirely in the parent.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;1. The HTML Template&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In the hrm-todos-summary HTML, inside the tab-pane where the todos are rendered, I injected a custom footer div immediately after the child widget line.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Location:&lt;/STRONG&gt; Inside the ng-repeat="todoLine in c.todoDisplayed[tab.name]"&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;HTML&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.todoDisplayed[tab.name].length &amp;amp;&amp;amp; todoLine.isOpen"&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"task-content"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-repeat&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine in c.todoDisplayed[tab.name]"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
  
  &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;sp-widget&lt;/SPAN&gt; &lt;SPAN class=""&gt;widget&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;sp-widget&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt; 
    
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"panel-footer"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"!todoLine.isCompleted"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
      &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;button&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"btn btn-default"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-click&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.requestClarification(todoLine)"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;${Request Clarification}&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;button&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
      &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;button&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"btn btn-default"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-click&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.rejectClarification(todoLine)"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;${Reject}&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;button&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
  
  &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"loading-indicator"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"!todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;span&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"fa fa-spinner fa-spin"&lt;/SPAN&gt; &lt;SPAN class=""&gt;aria-hidden&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"true"&lt;/SPAN&gt; &lt;SPAN class=""&gt;name&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"spinner"&lt;/SPAN&gt; &lt;SPAN class=""&gt;spin&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"true"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;span&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    ${Loading}...
  &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;2. The Client Script (Handling Modals)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I added functions to handle the button clicks. These functions use spModal to capture mandatory comments before sending the data to the server.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;JavaScript&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;c.requestClarification = &lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;todo&lt;/SPAN&gt;) &lt;/SPAN&gt;{
    &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!todo || !todo.sysId || !todo.tableName) &lt;SPAN class=""&gt;return&lt;/SPAN&gt;;

    spModal.prompt(&lt;SPAN class=""&gt;"Please enter clarification comments:"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;""&lt;/SPAN&gt;).then(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;commentText&lt;/SPAN&gt;) &lt;/SPAN&gt;{
        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!commentText) &lt;SPAN class=""&gt;return&lt;/SPAN&gt;; &lt;SPAN class=""&gt;// Handle cancel&lt;/SPAN&gt;

        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!commentText.trim()) {
            spUtil.addErrorMessage(&lt;SPAN class=""&gt;"Clarification comments are mandatory."&lt;/SPAN&gt;);
            &lt;SPAN class=""&gt;return&lt;/SPAN&gt;;
        }

        c.data.action = &lt;SPAN class=""&gt;"requestClarification"&lt;/SPAN&gt;;
        c.data.todo_sys_id = todo.sysId;
        c.data.todo_table = todo.tableName;
        c.data.comment_text = commentText.trim();

        c.server.update().then(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;response&lt;/SPAN&gt;) &lt;/SPAN&gt;{
            spUtil.addInfoMessage(&lt;SPAN class=""&gt;"Clarification requested successfully."&lt;/SPAN&gt;);
        });
    });
};

&lt;SPAN class=""&gt;// Similar logic added for c.rejectClarification&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;3. The Server Script (Backend Logic)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Instead of passing events, we handle the database updates directly in the parent widget's server script. This example updates the Approval record state and pushes the comments to the related RITM.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;JavaScript&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;if&lt;/SPAN&gt; (input &amp;amp;&amp;amp; input.action == &lt;SPAN class=""&gt;'requestClarification'&lt;/SPAN&gt;) {
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; grTodo = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; GlideRecordSecure(input.todo_table);
    &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (grTodo.get(input.todo_sys_id)) {
        &lt;SPAN class=""&gt;// 1. Update Approval State&lt;/SPAN&gt;
        grTodo.setValue(&lt;SPAN class=""&gt;'state'&lt;/SPAN&gt;, &lt;SPAN class=""&gt;'awaiting_clarification'&lt;/SPAN&gt;); &lt;SPAN class=""&gt;// Ensure this choice exists&lt;/SPAN&gt;
        grTodo.update();

        &lt;SPAN class=""&gt;// 2. Update Linked RITM with Comments&lt;/SPAN&gt;
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; ritmSysId = grTodo.getValue(&lt;SPAN class=""&gt;'document_id'&lt;/SPAN&gt;);
        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (ritmSysId) {
            &lt;SPAN class=""&gt;var&lt;/SPAN&gt; ritmGR = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; GlideRecord(&lt;SPAN class=""&gt;'sc_req_item'&lt;/SPAN&gt;);
            &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (ritmGR.get(ritmSysId)) {
                ritmGR.comments = input.comment_text;
                ritmGR.update();
            }
        }
    }
}&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;4. The CSS (The "Magic" Alignment)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To make these buttons look like they belong to the child widget, I used negative margins to pull the footer up. This prevents double borders and wasted whitespace.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;CSS&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;/* Target the custom footer */&lt;/SPAN&gt;
&lt;SPAN class=""&gt;.task-content&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;div&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;.panel-footer&lt;/SPAN&gt; {
    &lt;SPAN class=""&gt;text-align&lt;/SPAN&gt;: right;
    &lt;SPAN class=""&gt;border-top&lt;/SPAN&gt;: none;
    &lt;SPAN class=""&gt;padding-top&lt;/SPAN&gt;: &lt;SPAN class=""&gt;0.15rem&lt;/SPAN&gt;;
    &lt;SPAN class=""&gt;/* Adjust these margins based on your theme */&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;margin-right&lt;/SPAN&gt;: &lt;SPAN class=""&gt;10.15rem&lt;/SPAN&gt;; 
    &lt;SPAN class=""&gt;margin-top&lt;/SPAN&gt;: -&lt;SPAN class=""&gt;5rem&lt;/SPAN&gt;; 
    &lt;SPAN class=""&gt;background-color&lt;/SPAN&gt;: transparent;
}

&lt;SPAN class=""&gt;/* Ensure buttons display inline */&lt;/SPAN&gt;
&lt;SPAN class=""&gt;.task-content&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;div&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;.panel-footer&lt;/SPAN&gt; &lt;SPAN class=""&gt;.btn&lt;/SPAN&gt; {
  &lt;SPAN class=""&gt;display&lt;/SPAN&gt;: inline-block;
  &lt;SPAN class=""&gt;float&lt;/SPAN&gt;: none;
  &lt;SPAN class=""&gt;margin-left&lt;/SPAN&gt;: &lt;SPAN class=""&gt;5px&lt;/SPAN&gt;;
}&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;Why this approach?&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Simplicity:&lt;/STRONG&gt; You don't need to modify the task-configuration table or clone the standard approval widgets.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Context:&lt;/STRONG&gt; You have immediate access to the todoLine object in the parent loop.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Performance:&lt;/STRONG&gt; It reduces the number of event listeners required between parent and child widgets.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;I hope this helps anyone struggling with the EC To-do widget hierarchy!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;</description>
    <pubDate>Thu, 13 Nov 2025 11:15:05 GMT</pubDate>
    <dc:creator>divyashah</dc:creator>
    <dc:date>2025-11-13T11:15:05Z</dc:date>
    <item>
      <title>Adding Custom Action Buttons to the HRM Todos Summary Widget</title>
      <link>https://www.servicenow.com/community/community-central-forum/adding-custom-action-buttons-to-the-hrm-todos-summary-widget/m-p/3425939#M5403</link>
      <description>&lt;DIV class=""&gt;&lt;P&gt;Hi Community,&lt;/P&gt;&lt;P&gt;We all know that the standard Employee Center / HRSD To-do widget architecture is powerful, but it can be overwhelming to customize. The hierarchy usually looks something like this:&lt;/P&gt;&lt;P&gt;hrm-todos-summary -&amp;gt; hrm-todos-line-item -&amp;gt; task-configuration (or specific approval widgets).&lt;/P&gt;&lt;P&gt;Recently, I had a requirement to add &lt;STRONG&gt;"Request Clarification"&lt;/STRONG&gt; and &lt;STRONG&gt;"Reject with Comments"&lt;/STRONG&gt; buttons. The standard approach often involves cloning multiple child widgets or creating complex UI macros for the task configuration.&lt;/P&gt;&lt;P&gt;However, I found a cleaner way to achieve this by modifying the parent &lt;STRONG&gt;Custom HRM Todos Summary&lt;/STRONG&gt; widget directly. This keeps the logic centralized and avoids the "rabbit hole" of nested widget communication.&lt;/P&gt;&lt;P&gt;Here is how I achieved it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;The Concept&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Instead of trying to inject buttons into the child widgets, we can inject them into the ng-repeat loop of the parent widget. We use CSS to visually align them with the existing footer of the child widget, and we handle the logic (Modals + Server Updates) entirely in the parent.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;1. The HTML Template&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In the hrm-todos-summary HTML, inside the tab-pane where the todos are rendered, I injected a custom footer div immediately after the child widget line.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Location:&lt;/STRONG&gt; Inside the ng-repeat="todoLine in c.todoDisplayed[tab.name]"&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;HTML&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.todoDisplayed[tab.name].length &amp;amp;&amp;amp; todoLine.isOpen"&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"task-content"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-repeat&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine in c.todoDisplayed[tab.name]"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
  
  &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;sp-widget&lt;/SPAN&gt; &lt;SPAN class=""&gt;widget&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;sp-widget&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt; 
    
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"panel-footer"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"!todoLine.isCompleted"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
      &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;button&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"btn btn-default"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-click&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.requestClarification(todoLine)"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;${Request Clarification}&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;button&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
      &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;button&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"btn btn-default"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-click&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"c.rejectClarification(todoLine)"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;${Reject}&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;button&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
  
  &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;div&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"loading-indicator"&lt;/SPAN&gt; &lt;SPAN class=""&gt;ng-if&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"!todoLine.todoLineWidget"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;&amp;lt;&lt;SPAN class=""&gt;span&lt;/SPAN&gt; &lt;SPAN class=""&gt;class&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"fa fa-spinner fa-spin"&lt;/SPAN&gt; &lt;SPAN class=""&gt;aria-hidden&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"true"&lt;/SPAN&gt; &lt;SPAN class=""&gt;name&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"spinner"&lt;/SPAN&gt; &lt;SPAN class=""&gt;spin&lt;/SPAN&gt;=&lt;SPAN class=""&gt;"true"&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;span&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
    ${Loading}...
  &lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=""&gt;&amp;lt;/&lt;SPAN class=""&gt;div&lt;/SPAN&gt;&amp;gt;&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;2. The Client Script (Handling Modals)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I added functions to handle the button clicks. These functions use spModal to capture mandatory comments before sending the data to the server.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;JavaScript&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;c.requestClarification = &lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;todo&lt;/SPAN&gt;) &lt;/SPAN&gt;{
    &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!todo || !todo.sysId || !todo.tableName) &lt;SPAN class=""&gt;return&lt;/SPAN&gt;;

    spModal.prompt(&lt;SPAN class=""&gt;"Please enter clarification comments:"&lt;/SPAN&gt;, &lt;SPAN class=""&gt;""&lt;/SPAN&gt;).then(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;commentText&lt;/SPAN&gt;) &lt;/SPAN&gt;{
        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!commentText) &lt;SPAN class=""&gt;return&lt;/SPAN&gt;; &lt;SPAN class=""&gt;// Handle cancel&lt;/SPAN&gt;

        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (!commentText.trim()) {
            spUtil.addErrorMessage(&lt;SPAN class=""&gt;"Clarification comments are mandatory."&lt;/SPAN&gt;);
            &lt;SPAN class=""&gt;return&lt;/SPAN&gt;;
        }

        c.data.action = &lt;SPAN class=""&gt;"requestClarification"&lt;/SPAN&gt;;
        c.data.todo_sys_id = todo.sysId;
        c.data.todo_table = todo.tableName;
        c.data.comment_text = commentText.trim();

        c.server.update().then(&lt;SPAN class=""&gt;&lt;SPAN class=""&gt;function&lt;/SPAN&gt; (&lt;SPAN class=""&gt;response&lt;/SPAN&gt;) &lt;/SPAN&gt;{
            spUtil.addInfoMessage(&lt;SPAN class=""&gt;"Clarification requested successfully."&lt;/SPAN&gt;);
        });
    });
};

&lt;SPAN class=""&gt;// Similar logic added for c.rejectClarification&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;3. The Server Script (Backend Logic)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Instead of passing events, we handle the database updates directly in the parent widget's server script. This example updates the Approval record state and pushes the comments to the related RITM.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;JavaScript&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;if&lt;/SPAN&gt; (input &amp;amp;&amp;amp; input.action == &lt;SPAN class=""&gt;'requestClarification'&lt;/SPAN&gt;) {
    &lt;SPAN class=""&gt;var&lt;/SPAN&gt; grTodo = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; GlideRecordSecure(input.todo_table);
    &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (grTodo.get(input.todo_sys_id)) {
        &lt;SPAN class=""&gt;// 1. Update Approval State&lt;/SPAN&gt;
        grTodo.setValue(&lt;SPAN class=""&gt;'state'&lt;/SPAN&gt;, &lt;SPAN class=""&gt;'awaiting_clarification'&lt;/SPAN&gt;); &lt;SPAN class=""&gt;// Ensure this choice exists&lt;/SPAN&gt;
        grTodo.update();

        &lt;SPAN class=""&gt;// 2. Update Linked RITM with Comments&lt;/SPAN&gt;
        &lt;SPAN class=""&gt;var&lt;/SPAN&gt; ritmSysId = grTodo.getValue(&lt;SPAN class=""&gt;'document_id'&lt;/SPAN&gt;);
        &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (ritmSysId) {
            &lt;SPAN class=""&gt;var&lt;/SPAN&gt; ritmGR = &lt;SPAN class=""&gt;new&lt;/SPAN&gt; GlideRecord(&lt;SPAN class=""&gt;'sc_req_item'&lt;/SPAN&gt;);
            &lt;SPAN class=""&gt;if&lt;/SPAN&gt; (ritmGR.get(ritmSysId)) {
                ritmGR.comments = input.comment_text;
                ritmGR.update();
            }
        }
    }
}&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;4. The CSS (The "Magic" Alignment)&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To make these buttons look like they belong to the child widget, I used negative margins to pull the footer up. This prevents double borders and wasted whitespace.&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN class=""&gt;CSS&lt;/SPAN&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;/* Target the custom footer */&lt;/SPAN&gt;
&lt;SPAN class=""&gt;.task-content&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;div&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;.panel-footer&lt;/SPAN&gt; {
    &lt;SPAN class=""&gt;text-align&lt;/SPAN&gt;: right;
    &lt;SPAN class=""&gt;border-top&lt;/SPAN&gt;: none;
    &lt;SPAN class=""&gt;padding-top&lt;/SPAN&gt;: &lt;SPAN class=""&gt;0.15rem&lt;/SPAN&gt;;
    &lt;SPAN class=""&gt;/* Adjust these margins based on your theme */&lt;/SPAN&gt;
    &lt;SPAN class=""&gt;margin-right&lt;/SPAN&gt;: &lt;SPAN class=""&gt;10.15rem&lt;/SPAN&gt;; 
    &lt;SPAN class=""&gt;margin-top&lt;/SPAN&gt;: -&lt;SPAN class=""&gt;5rem&lt;/SPAN&gt;; 
    &lt;SPAN class=""&gt;background-color&lt;/SPAN&gt;: transparent;
}

&lt;SPAN class=""&gt;/* Ensure buttons display inline */&lt;/SPAN&gt;
&lt;SPAN class=""&gt;.task-content&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;div&lt;/SPAN&gt; &amp;gt; &lt;SPAN class=""&gt;.panel-footer&lt;/SPAN&gt; &lt;SPAN class=""&gt;.btn&lt;/SPAN&gt; {
  &lt;SPAN class=""&gt;display&lt;/SPAN&gt;: inline-block;
  &lt;SPAN class=""&gt;float&lt;/SPAN&gt;: none;
  &lt;SPAN class=""&gt;margin-left&lt;/SPAN&gt;: &lt;SPAN class=""&gt;5px&lt;/SPAN&gt;;
}&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;Why this approach?&lt;/H3&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Simplicity:&lt;/STRONG&gt; You don't need to modify the task-configuration table or clone the standard approval widgets.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Context:&lt;/STRONG&gt; You have immediate access to the todoLine object in the parent loop.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;STRONG&gt;Performance:&lt;/STRONG&gt; It reduces the number of event listeners required between parent and child widgets.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;I hope this helps anyone struggling with the EC To-do widget hierarchy!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;</description>
      <pubDate>Thu, 13 Nov 2025 11:15:05 GMT</pubDate>
      <guid>https://www.servicenow.com/community/community-central-forum/adding-custom-action-buttons-to-the-hrm-todos-summary-widget/m-p/3425939#M5403</guid>
      <dc:creator>divyashah</dc:creator>
      <dc:date>2025-11-13T11:15:05Z</dc:date>
    </item>
  </channel>
</rss>

