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

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'
});

DrewW
Mega Sage
Mega Sage

americo
Tera Contributor


Thank you so much Drew, your insights were right , I really appreciated your help, I can continue building stuff and I would continue playing around with components, my next attempt is to use existing components and incorporate them in my own custom component. For now I'm good with pulling data from ServiceNow. I certainly would keep posting for help ðŸ™‚

Ran6
Tera Contributor

i have similar issue, i am trying to pass the incident nunber/Caller id to the component as he's added as related item.