Alpha Snippets
Please Get Familiar With These Topics
- jsonata: https://jsonata.org/
- lodash.get: https://lodash.com/docs/4.17.15#get
- Shadow root: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
Grab the DOM instance of any element
const element = ap.$('<element_id>') // element_id can be copied from attribute window
// element is an instance of Element: https://developer.mozilla.org/en-US/docs/Web/API/Element
Log the parameters sent to the custom code
// might have `triggerEvent` (when invoked as a trigger), `response` (if API)
console.log(params)
Set a property on a DOM instance
ap.$('<element_id>', 'propertyToSet', propertyValue)
Set dropdown options programmatically
// set `dropDownInstance.options.options` to params.response?.<key>
ap.$('b39100f8-45ae-41f0-a259-22e18736d690', 'options.options', params.response?.records || []);
/**
* set where the displayValue for each item is looked up from the bound options.options value
* -- signature: ap.$(dropDownId, lodash.get compatible path, jsonata expression)
* jsonata: https://jsonata.org/
* lodash.get: https://lodash.com/docs/4.17.15#get
*/
ap.$('b39100f8-45ae-41f0-a259-22e18736d690', 'options.displayValue', '$."Article(EN)"');
// set where the displayValue for each item is looked up from the bound options.options value
ap.$('b39100f8-45ae-41f0-a259-22e18736d690', 'options.displayLabel', '$."Article(EN)"');
Set a HTML attribute on an element instance
// grab the DOM instance of element
const element = ap.$('dd55fdf9-3be0-4bbb-88e0-2ec5a41a1735');
// set attribute: https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
element.setAttribute('huehuehue', 'true')
Trigger DATASOURCE of dropdown
const dropdown = ap.$('dropdown_id');
dropdown.dispatchEvent(
new CustomEvent('alpha-renderer:dataSource', {
detail: { refresh: true },
})
);
Open Dialog using custom code
const pages = await ap.pages.get();
console.log(pages)
const newPage = pages.find((el)=> [el.name](http://el.name/) == 'Page name');
ap.dialog.open({
page: newPage,
height:'50',
width: '50',
header: 'Title'
})
Navigate to task pages
const pages = await ap.pages.get();
console.log(pages);
const newPage = pages.find((el)=> [el.name](http://el.name/) == 'Page name');
ap.navigate({
page: newPage
pageId: newPage.pageId,
name: [newPage.name](http://newpage.name/)
})
Trigger On Table Refresh triggers programmatically
const table = ap.$('8f90e0eb-eb23-4e57-b574-5933b912cbc8');
table.dispatchEvent(
new CustomEvent('alpha-table:on-table-refresh', {
// For pagination pass the details as given below
detail: {
pageNumber: table.pageNumber,
pageSize: table.rows
},
bubbles: true,
composed: true,
})
);
Refresh data source for any alpha-element ( Table, dropdown)
window.dispatchEvent(
// The event name should be exactly this: "alpha_element:connected_callback"
new CustomEvent('alpha_element:connected_callback', {
detail: {
element: ap.$(<id>),
},
})
);
How to Refresh a Table After Uploading a File to DMS
Please read this document to achieve this:
https://docs.google.com/document/d/1xpKXRZ3NqQQ4YCRfoYCPuL0kuNSJibASYSutfa1gHQs/edit?usp=sharing
Listen For Change Event Of All the leaves in renderer
// get the current page's renderer DOM instance
const r = document.querySelector('alpha-renderer');
// `rendererMetadata` holds a map of `id` of the renderer descendents and its metadata
// get all the element Ids into `leafs`
const leafs = Object.keys(r.rendererMetaData)
// Add `change` listener on every leaf component.
// And, in the listener callback you can add conditions to disable button or
// get any leafs value (refer above snippets) or anything and update the
// leafs properties
leafs.forEach(l => ap.$(l).addEventListener('change', (e) => console.log({ l, valid: document.querySelector('alpha-renderer').valid }, e)));
ap.$('0e470eef-cf69-434b-9ea6-5bd054ab100b', 'disabled', true);
Get renderer validity
const r = ap.$(<page-id>);
console.log(r.valid)
For-loop Configuration and Contextual Indexing Guide
Overview
When designing dynamic components, a for-loop is a configuration used to iterate over a given data source, which must be an array. This for-loop mechanism is used to render multiple instances of a component (Panel, Section, or Leaf) based on the number of elements in the array. During the rendering process, each instance is assigned a unique contextual index to identify its position within the array.
Mapping sources for data source
- co
- local
How Contextual Indexing Works
Whenever a data source is assigned to a Panel, Section, or Leaf using a for-loop, a corresponding context is created to track the current index during iteration:
i: Represents the index for Panels.j: Represents the index for Sections.k: Represents the index for Leaf.
The context indices (i, j, k) help in accessing specific elements from the data source during custom configuration and logic execution.
Contextual Index Mapping
The index mapping is structured as follows:
-
Panel: Uses the
iindex for each item in its data source. -
Section: Uses the
jindex for each item in its nested data source. -
Leaf: Uses the
kindex for each item in its nested data source. -
Configuration guide
-
Configure a for loop on panel
-
co.users["John","Dave" ]
-
-
Inside panel add a section and configure for-loop data source as
-
co.components[ { field:'input' }, { field:'date' } ]
-
-
Inside section drop a
text-fieldanddate-pickercomponent- On text-field add a dependency if
co.components[j].fieldequals āinputā then show and set output binding variable asco.users[i] - On date-picker add a dependency if
co.components[j].fieldequals ādateā then show - Point to Note
- To access a value of panelās data source we used
ias index to bind user as input field value - Similarly access a value of sectionās data source we used
jas index to resolve dependency for conditional rendering of leaf
- To access a value of panelās data source we used
- On text-field add a dependency if
-
Tabs
1. enableTab(tabIndex: number)
Enables a tab by setting its disabled state to false.
-
Parameters:
tabIndex(number): The index of the tab to enable.
-
Example:
tabInstance.enableTab(2); // Enables the tab at index 2
2. disableTab(tabIndex: number)
Disables a tab by setting its disabled state to true.
-
Parameters:
tabIndex(number): The index of the tab to disable.
-
Example:
tabInstance.disableTab(1); // Disables the tab at index 1
3. toggleVisibility(tabIndex: number)
Toggles the visibility of a tab by switching its visible property.
-
Parameters:
tabIndex(number): The index of the tab whose visibility is to be toggled.
-
Example:
tabInstance.toggleVisibility(0); // Toggles the visibility of the tab at
4. setActiveTab(tabIndex: number, emitEvent: boolean = true)
Sets a tab as the active tab.
-
Parameters:
tabIndex(number): The index of the tab to set as active.emitEvent(boolean): Optional. Whether to emit a selection event. Defaults totrue.
-
Example:
tabInstance.setActiveTab(3); // Sets the tab at index 3 as the active tab
5. setDefaultTab(tabIndex: number)
Sets a tab as the default tab (if the tab is enabled and visible).
-
Parameters:
tabIndex(number): The index of the tab to set as default.
-
Example:
// Sets the tab at index 0 as the default tab tabInstance.setDefaultTab(0);
Enquiry - change readonly state of particular component
//Page- On Init triiger
const elementInstance = ap.$('<element-id>')
elementInstance.readonly=false;
//for button , checkbox, radio-button elements
elementInstance.disabled=false;
Action on page click on case-details sidenav
const pageSidenavElement = document.querySelector("app-main-sidenav");
if (pageSidenavElement) {
const pageContainers = pageSidenavElement.querySelectorAll(
"div.hover\\:surface-hover.border-round-lg"
);
pageContainers.forEach((pageContainer) => {
const pageLabelElement = pageContainer.querySelector("span");
//Write custom logic on page name click on sidenav
//Example: Prevent navigation on click of page - dropdown_test ,
// instead open a dialog - document viewer
if (span && pageLabelElement.textContent.trim() === "dropdown_test") {
pageContainer.addEventListener(
"click",
async (event) => {
event.preventDefault();
event.stopPropagation();
console.log("Custom logic executed for dropdown_test");
const pages = await ap.pages.get();
console.log(pages);
const newPage = pages.find((el) => el.name == "document viewer");
ap.dialog.open({
page: newPage,
height: "50",
width: "50",
header: "Title",
});
},
{ capture: true }
);
}
});
}
Lifecycle hooks config for all kinds of inbox
On Init:
- Triggered when the inbox items (case and task instances) are fetched from the backend. Use this to modify the inbox data before rendering.
- Parameters passed to the custom code:
data: The inbox data fetched from the backend.
After View Init:
- Triggered after the inbox items are rendered on the UI. Use this to perform any post-rendering operations.
- Parameters passed to the custom code:
data: The inbox data fetched from the backend.element: Reference to the DOM instance of the inbox table.
Note: All the parameters passed to the custom code can be seen by logging the params object in the console like this:
console.log(params);
Style Inbox Table Cells Based On the value
- Every cell in the inbox table can be styled based on the value of the cell using the css editor using the
data-prefix - The format for selecting a cell is =>
[data-column-name="column name"][data-column-value="column value"] - To select one of the default inboxes use =>
.inbox-myTasks,.inbox-groupTasks,.inbox-teamTasks - To select a custom filter use =>
.inbox-{inbox name or custom filter name (spaces replaced with '-'s} - The format for selecting inbox is =>
.inbox-{inbox name or custom filter name (spaces replaced withs} - To select a column header use =>
.{inbox-selector} th[data-column-name="column name"]
/* .inbox-{inbox name or custom filter name (spaces replaced with `-`s} */
.inbox-My-Task [data-column-name='Age'][data-column-value='2d'] {
background-color: red;
}
/* For enquiry inbox */
.enquiry-inbox-Default[data-column-name='Status'][data-column-value='Pending'] {
background-color: red;
}
/* For admin inbox */
.admin-inbox-Default [data-column-name='Status'][data-column-value='Pending'] {
background-color: red;
}
NOTE: You might have to use !important to override the default styles.
Show toast message programmatically
ap.toast.showToast({
status: "success", // Toast status, e.g., 'success', 'error', 'info', or 'warn'
title: "Title", // Title of the toast notification
message: "message", // Message content to be displayed
});
ļø Use lodash (ap._) and momentjs (ap.moment) functions in ap namespace!
Using lodash:
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alicia' }, // Duplicate id
{ id: 3, name: 'Charlie' },
{ id: 2, name: 'Bobby' } // Duplicate id
];
await alpha.local.update('uniqueUsers', ap._.uniqBy(users, 'id'));
console.log(alpha.local.get().uniqueUsers);
/*
[
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
]
*/
Add Custom Validation For A Form Field
ap.renderer.validations.add(leafId, keyName, functionRef, validateOnAdd);
/**
* @param {string} leafId - The leaf id of the form field (can be copied from the attribute window header in workflow studio).
* @param {string} keyName - The unique name for the validation function. ex. 'validateAge', 'validateCompanyMailId' etc
* @param {function} functionRef - The callback function to be executed for validation. It will be called with the value of the form field as the first argument.
* The function should return an object with the following structure:
* {
* valid: true/false, // true if the validation passes, false otherwise
* error: 'Error message to be shown if the validation fails' // The error message to be shown if the validation fails
* }
* @param {boolean} validateOnAdd - If true, the validation function will be executed when the form field is added to the form and error will be shown if the validation fails.
*/
// Example:
ap.renderer.validations.add(
"leafId",
"validateIfAdult",
(leafInstance) => {
if (leafInstance.value < 18) {
return {
valid: false,
error: {
message: "Age should be greater than 18",
},
};
}
return {
valid: true,
};
},
true,
);
