Agent Workspace custom component using Http Effects working example, now I need to pass parameters dynamically any ideas?

americo
Tera Contributor

Hi there,

I previously posted this question as having issues to pull data from ServiceNow but now I'm successful doing that, How did I fix this?

First of all, before using now-cli develop make sure you do the follow steps:

1) Even though the web site says to not include password, please make sure you have included it in your now-cli.json as per below example:

{
  "development": {
    "proxy": {
      "origin": "https://<your instance>.service-now.com",
      "headers": {
        "Authorization": "Basic <Base 64 username:password>"
      },
      "proxies": ["/api"]
    },
 }
 
NOTE: I'm not sure about this yet, if you have any inputs I'm open to feedback, I was not able to figure out how to not include this Authorization
 

2) Log to your PDI (Personal Instance) using: now-cli login --host "https://<your instance>.service-now.com" --username user --password password

3) Then start local server using now-cli develop

4) You won't have issues while calling Http Effects

Boila! you can now enjoy and develop your custom component

You can use below code in your local environment and once you are ready you can deploy it to your PDI, refer to the screenshot of how it looks like once deploy (you must set it up in your UI Builder)

Example:

import {createCustomElement, actionTypes} from '@servicenow/ui-core';
import {createHttpEffect} from '@servicenow/ui-effect-http';
import snabbdom from '@servicenow/ui-renderer-snabbdom';
import styles from './styles.scss';

const {COMPONENT_BOOTSTRAPPED} = actionTypes;
const USER_FETCH_REQUESTED = "USER_FETCH_REQUESTED";
const USER_FETCH_SUCCEEDED = "USER_FETCH_SUCCEEDED";
const USER_FETCH_FAILED = "USER_FETCH_FAILED";

const ACTION_ON_DISMISS = "ACTION_ON_DISMISS";
const ACTION_ON_SEARCHCHANGE = "ACTION_ON_SEARCHCHANGE";

const onDismiss = (coeffects) => {
    const {action, state, updateState} = coeffects;
    const isNotId = item => item.sys_id !== action.payload.id;
    const updatedList = state.result.filter(isNotId);
    updateState( { result: updatedList } );
};

const onSearchChange = (coeffects) => {
    const {action, updateState} = coeffects;
    updateState( { searchTerm: action.payload.searchTerm } );
};

const fetchUsers = createHttpEffect(`api/now/table/sys_user?sysparm_limit=10&sysparm_query=nameLIKEAnna`, {
    queryParams: ["sysparm_limit=10"],
    successActionType: USER_FETCH_SUCCEEDED,
    errorActionType: USER_FETCH_FAILED,
});

const parseResponse = (coeffects) => {
    const {action, updateState} = coeffects;
    updateState( { result: action.payload.result } );
};

const view = (state, {updateState, dispatch}) => {
    const welcome = "Welcome to UI-Components";
    const {searchTerm} = state;
    return (
        <div>
            <h2>{welcome}</h2>
            <div>
                Name: <input
                    type="text"
                    value={searchTerm}
                    on-change={(event) => dispatch(ACTION_ON_SEARCHCHANGE, { searchTerm: event.target.value })}
                />
                <button
                    type="button"
                    on-click={(event) => dispatch(USER_FETCH_REQUESTED)}
                    >
                    Search
                </button>
            </div>
            <div><span>Showing results for: {searchTerm}</span></div>
            {
                state.result ?
                    state.result.map(item => {
                        const url = "./sys_user.do?sys_id=" + item.sys_id;
                        return (
                            <div key={item.sys_id}>
                                <span><a href={url}>{item.user_name}</a></span>
                                <span>{item.name}</span>
                                <span>{item.email}</span>
                                <span>{item.sys_created_on}</span>
                                <span>
                                    <button
                                        on-click={() => dispatch(ACTION_ON_DISMISS, { id: item.sys_id })}
                                        type="button"
                                        >
                                        Dismiss
                                    </button>
                                </span>
                            </div>
                        )
                })
                : null
            }
        </div>
    );
};

createCustomElement('x-34391-example-http-01', {
    renderer: {type: snabbdom},
    initialState: {
        result: null,
        searchTerm: 'Anna',
    },
    /*eventHandlers: [{
        events: ['click'],
        effect({action: {payload: {event, host}}}) {
            console.log(event);
            console.log(host);
        },
    }],*/
    actionHandlers: {
        [ACTION_ON_DISMISS]: {
            effect: (coeffects) => onDismiss(coeffects),
            args: [],
            interceptors: [],
            stopPropagation: true
        },
        [ACTION_ON_SEARCHCHANGE]: {
            effect: (coeffects) => onSearchChange(coeffects),
            args: [],
            interceptors: [],
            stopPropagation: true
        },
        [USER_FETCH_SUCCEEDED]: {
            effect: (coeffects) => parseResponse(coeffects),
            args: [],
            interceptors: [],
            stopPropagation: true,
        },
        [USER_FETCH_FAILED]: {
            effect: (coeffects) => parseResponse(coeffects),
            args: [],
            interceptors: [],
            stopPropagation: true,
        },
        [USER_FETCH_REQUESTED]: fetchUsers,
        [COMPONENT_BOOTSTRAPPED]: {
            effect: (coeffects) => {
                const {dispatch} = coeffects;
                dispatch('USER_FETCH_REQUESTED');
            },
            args: [],
            interceptors: [],
            stopPropagation: true,
        },
    },
    view,
    styles,
});


​
 
To add to your UI Builder modify your now-ui.json

	"components": {
	    "x-34391-example-http-01": {
	        "innerComponents": [],
			"uiBuilder": {
				"associatedTypes": ["global.core"],
				"label": "Magic",
				"icon": "chat-fill",
				"description": "Magic!"
			}
	    }
	},
 
What's next? I need help with using Http Effects, I can't figure out yet how to send parameters dynamically. I tried using queryParams as stated in this link but didn't work : ( ... as of now I just hard coded the values as you can see, also please let me know if my implantation is correct, I have doubts if it was done properly or any suggestions.
 
find_real_file.png
 
Spread the word about components!
1 ACCEPTED SOLUTION

DrewW
Mega Sage
Mega Sage

This is how you can go about it.

const getTableData = createHttpEffect('/api/now/table/:table', {
    method: 'GET',
	pathParams: ['table'],
    queryParams: [
                    'sysparm_query',
                    'sysparm_display_value',
                    'sysparm_exclude_reference_link',
                    'sysparm_suppress_pagination_header',
                    'sysparm_fields',
                    'sysparm_limit',
                    'sysparm_view',
                    'sysparm_no_count'
                ],
    startActionType: AIG_DATA_REQUEST_STARTED,
    progressActionType: AIG_DATA_REQUEST_PROGRESS,
    successActionType: AIG_DATA_SUCCEEDED,
    errorActionType: AIG_DATA_FAILED
});

//Dispatch will look like
dispatch(AIG_ROW_DATA_REQUESTED, {
	table: 'u_bok_aig',
	sysparm_query: 'u_active=true^u_section=' + element.sys_id + '^ORDERBYu_order',
	sysparm_fields: 'u_active, u_name, u_start, u_end, u_account, sys_id',
	sysparm_display_value: 'true'
});

View solution in original post

11 REPLIES 11

Tommy Jensen
Giga Guru

Can you tell me the steps to put a custom component on the incident page?

Hi Tommy,

You can add your custom component to show in incident by creating a Contextual Side Panel record. Simply go to Actions & Components then Contextual Side Panel and create new. There you can define which component to use and for which table should show in agent workspace, the Advanced view lets you define conditions and roles of who can see this component.

 

find_real_file.png

 

Thank you 🙂

Sonia1
Kilo Contributor

I tried the example that you have mentioned here, the components gets created, deployed correctly too but the screen is blank. No output is shown.Can you let me know where can be the mistake?

americo
Tera Contributor

HI Sonia,

When you run this locally does it load any content or shows a blank page? In my case It helped me to check the browser console for any errors when this happens, can you show what is coming at your end?