Bring Your Own (BYO) 7.26 Implementation Examples
The Bring Your Own framework is intended for developers who have a strong understanding of the Unqork Designer Platform and JavaScript JavaScript is an object-oriented computer programming language. It is most-commonly used for interactive effects in the browser..
Overview
The Bring Your Own (BYO) 7.26 implementation examples page contains example implementations of a component, event, and operation. Refer to these exampless when building your components with the BYO Component SDK guide.
AG Grid Component
This example displays the customization options, manifest.json, and implementation of a custom AG Grid component.
Configuration
Settings | Object Type | Description |
---|---|---|
columnDefinitions |
string componentKey |
The definitions of the columns from the key and label data. |
value |
string componentKey |
The value of the grid data. This version accepts a string A string is an object that represents a sequence of characters. Strings typically hold data represented in text form., but it can be defined as needed. |
Events
Event Name | Event Value | Description |
---|---|---|
Cell Clicked |
agGridCellClicked |
Add a custom event that emits on cell click. Event Payload: Add the details of the cell that was clicked into the Event Payload to use in logic:
|
Example AG Grid Package
Click on each of the tabs below to view the JSON JSON (JavaScript Object Notation) is an open standard file and data interchange format. Unqork uses JSON for submission (record) data. and Javascript required to implement an AG Grid:
Manifest JSON Example
Get an in-depth understanding of manifest.json specifications in our Bring Your Own (BYO): Understanding the manifest.json File article.
{
"name": "AgGrid",
"version": "1.0.0",
"main": "agGrid.js",
"type": "custom",
"productType": "BYO",
"description": "AG Grid integration with Unqork",
"components": [
{
"name": "AG Grid",
"type": "agGrid",
"description": "AG Grid component for Unqork",
"model": {
"type": "object",
"properties": {
"columnDefinitions": {
"name": "Column Definitions",
"type": "array",
"description": "Column definitions for this grid (currently only supporting key and label)",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Unique key for the column"
},
"label": {
"type": "string",
"description": "Display label for the column"
}
}
}
},
"value": {
"name": "Grid Data (JSON)",
"type": "string",
"description": "JSON string of data for the grid"
}
},
"required": ["columnDefinitions"]
},
"events": [
{
"name": "AG Grid Cell Clicked",
"type": "agGridCellClicked",
"description": "This event is triggered when the user clicks on a grid cell.",
"stability": "STABLE"
}
]
}
]
}
agGrid.js
The implementation javascript file name must match the manifest.json's main value. In this example, the agGrid.js file matches line four in the manifest.
/// AgGrid Import (removed for to make file legible) ///
class UnqorkAgGridComponent extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.gridOptions = {
columnDefs: [],
rowData: [],
}
}
/**
* This is the only required method to integrate with the Unqork system
*
* @param {*} api The interface to the Unqork Runtime, used for both
* monitoring state and emitting events
*/
initialize(api) {
this.config = api.state.currentState()
this.api = api
if (this.config.columnDefinitions?.length) {
const defs = this._normalizeInput(this.config.columnDefinitions)
this.gridOptions.columnDefs = this._formatColumnDefinitions(defs)
}
if (this.config.value?.length) {
this.gridOptions.rowData = this._normalizeInput(this.config.value)
}
this.renderGrid(this.shadowRoot, this.gridOptions)
this.subscribeColumnDefs()
this.subscribeData()
}
/**
* Subscribe to the source for column definitions
*
* This can be made more robust by first using
* api.state.state$('columnDefsReference') to subscribe to
* any changes to that value (i.e. the target key), and then using
* resolveByKey$ to resolve the current value of that key, but
* keeping it simple for example here
*/
subscribeColumnDefs() {
this
.api
.state
.state$('columnDefinitions').subscribe((columnDefs) => {
console.log('AG Grid column definitions updated to', columnDefs)
// This _should_ be an array, but sometimes components try to set it as a
// JSON string instead, so we handle that here
const value = typeof(columnDefs) === 'string' ? JSON.parse(columnDefs) : columnDefs
this.gridOptions = {
rowData: this.gridOptions.rowData,
columnDefs: value ? this._formatColumnDefinitions(value) : [],
}
this.updateGrid(this.gridOptions)
})
}
subscribeData() {
this.api.state.state$('value').subscribe((rowData) => {
console.log('AG Grid value updated to', rowData)
// We support setting this as a JSON string or already parsed array of objects
// so handle that here
const value = typeof(rowData) === 'string' ? JSON.parse(rowData) : rowData
this.gridOptions = {
rowData: value || [],
columnDefs: this.gridOptions.columnDefs,
}
this.updateGrid(this.gridOptions)
})
}
updateGrid(gridOptions) {
console.log('Updating AG Grid', gridOptions)
this.gridApi.updateGridOptions(gridOptions)
}
async renderGrid(document, gridOptions) {
console.log('Rendering AG Grid component', {gridOptions, agGrid, windowAgGrid: window.agGrid})
document.innerHTML = this.view()
this.gridEl = document.querySelector('#myGrid')
this.gridApi = window.agGrid.createGrid(this.gridEl, gridOptions)
// Set this here so that it doesn't overridden when we update gridOptions
this.gridApi.addEventListener('cellClicked', (ev) => {
console.log('Emitting AG Grid Cell Clicked Event', ev)
this.emitCellClickedEvent(ev)
})
console.log('Created AG Grid', {
document,
gridOptions,
gridEl: this.gridEl,
gridApi: this.gridApi,
})
}
// Emit an event when a cell is clicked
// Full docs: https://www.ag-grid.com/javascript-data-grid/grid-events/#reference-selection-cellClicked
emitCellClickedEvent = (ev) => {
this.api.events.emit({
name: 'onAgGridCellClicked',
payload: ev
})
}
view() {
return `
<div id="myGrid" style="height: 500px"></div>
`
}
/**
* Input data can be either JSON string or actual data, due to
* Unqork data constraints, so ensure it's proper data before
* using
*/
_normalizeInput(val) {
return typeof(val) === 'string' ? JSON.parse(val) : val
}
/**
* We store column definitions with standard key/label properties
* But AG Grid using different property names, so we map it here
*/
_formatColumnDefinitions(defs) {
return defs.map(({key, label}) => {
return {
field: key,
headerName: label ?? key
}
})
}
}
// This definition defines the state settings (model) for this component
// It mirrors the fuller description in manifest.json and will
// eventually be used to auto-generate the manifest.json JSON schema
class AgGridDefinition {
columnDefsReference
dataReference
}
// Actual export that exposes both the view layer and the model
// and is consumed by the Unqork Runtime for both configuration and
// execution
// All of these are `async` to allow for us to load them on demand
// without impacting initial page load performance
export const agGrid = {
model: async () => AgGridDefinition,
view: async () => UnqorkAgGridComponent,
}
// This definition describes the schema of the event that is emitted
// when the user clicks on an item
class CellClicked {
name = 'agGridCellClicked'
payload = {
index,
text,
}
}
// This export is used to expose the event to the Unqork Runtime
export const agGridCellClicked = {
model: async () => CellClicked,
}
Understand what's required to build a custom component in BYO Component SDK article.
Root Level Event
This example displays the Manifest JSON and JavaScript implementation of a custom event. After uploading a package containing an event asset, Creators Also known as Unqork Users, or Designer Users; is anyone who is inside the Unqork platform. can use the event in the Operations Builder.
Click on each of the tabs below to view the JSON and Javascript required to implement a root level event:
Manifest JSON Example
Get an in-depth understanding of manifest.json specifications in our Bring Your Own (BYO): Understanding the manifest.json File article.
{
"name": "eventsOnly",
"version": "1.0.0",
"main": "eventsOnly.js",
"type": "custom",
"productType": "BYO",
"description": "Asset that contains only general events.",
"events": [
{
"name": "Events Only",
"type": "eventsOnly",
"description": "A top-level event.",
"stability": "ALPHA",
"model": {
"type": "object",
"properties": {
"name": {
"const": "eventsOnly",
"type": "string"
},
"payload": {
"type": "object",
"properties": {
"data": {
"description": "Sample property",
"type": "string"
}
}
}
}
}
}
]
}
eventsOnly.js
The implementation JavaScript file name must match the manifest.json's main value. In this example, the eventsOnly.js file matches line four in the manifest.
class EventPayload {
data = 'defaultValue'
}
class Event {
name = 'eventsOnly'
payload = new EventPayload()
}
// Export for the event
export const eventsOnly = {
model: async () => Event,
}
Understand what's required to build a custom component in BYO Component SDK article.
Root Level Operation
This example displays an example of the Manifest JSON and JavaScript implementation of a custom operation. After uploading a package containing an operation asset, Creators can use the operation in the Operations Builder.
Click on each of the tabs below to view the JSON and Javascript required to implement a root level operation:
Manifest JSON Example
Get an in-depth understanding of manifest.json specifications in our Bring Your Own (BYO): Understanding the manifest.json File article.
{
"name": "operationsOnly",
"version": "1.0.0",
"main": "operationsOnly.js",
"type": "custom",
"productType": "BYO",
"description": "Asset that contains only general operations.",
"operations": [
{
"name": "Operations Only",
"type": "operationsOnly",
"description": "An operation to transform data.",
"stability": "STABLE",
"model": {
"definitions": {
"OperationOptions": {
"type": "object",
"properties": {
"input": {
"description": "Input component for the operation.",
"type": "string"
},
"output": {
"description": "Output component for the operation.",
"type": "string"
}
},
"required": ["input"]
}
},
"properties": {
"options": {
"$ref": "#/definitions/OperationOptions"
},
"type": {
"const": "operationsOnly",
"type": "string"
}
},
"required": ["options"],
"type": "object"
},
"contextModel": {
"type": "object",
"properties": {
"result": {
"type": "object",
"properties": {
"transformed": { "type": "string", "description": "Transformation result" }
}
}
}
}
}
]
}
operationsOnly.js
The implementation JavaScript file name must match the manifest.json's main value. In this example, the operationsOnly.js file matches line four in the manifest.
class OperationOptions {
input
output
}
class Operation {
type = 'operationsOnly'
options = new OperationOptions()
}
class OperationHandler {
execute(operation, api) {
const input = api.state.resolveByKey(operation.options.input)
const output = api.state.resolveByKey(operation.options.output)
const newValue = 'transformed ' + input.value
api.state.set(output.key, { value: newValue })
return {
transformed: newValue,
}
}
}
class OperationContextResult {
transformed
}
class OperationContext {
result = new OperationContextResult()
}
// Export for the operation
export const operationsOnly = {
model: async () => Operation,
handler: async () => OperationHandler,
contextModel: async () => OperationContext,
}
Understand what's required to build a custom component in BYO Component SDK article.
Resources
Bring Your Own (BYO) Framework Landing Page
Find all the resources needed to build your own components here.
Introduction to the Bring Your Own (BYO) Framework
Get started building your own custom assets, including components, events, and operations.
Create a BYO Package
Understanding the manifest.json File
Learn about the file's specification, component and event definitions.
Understanding the BYO Runtime Engine API
Discover the interface between your custom BYO components and the Unqork platform.
Custom Component SDK
Extend component functionality in the Unqork Designer Platform.
Custom Component
Understand the state, interface, and events of a custom component.
BYO Best Practices
Learn about best practices for implementing and using BYO assets.