Logo REKA Advanced

Platform Knowledge Base

Comprehensive guides and documentation for designing, building, and managing enterprise applications on the REKA / LEAP platform.

Pre-requisites for Advanced Topics
  • REKA Beginner Level training completed.
  • Familiarity with HTML and JavaScript.
  • Understanding of backend (server) and frontend (UI) concepts.
  • Reference: REKA Glossary

Select a topic from the sidebar folder navigation to explore the detailed advanced functionalities of the REKA platform.

1. Form Design

1.1 Single Data

The Single Data option ensures that only one record exists for a given qualifier (criteria).

  • If no matching data exists → a new entry will be created.
  • If matching data exists → the existing entry will be loaded for update.

How to Enable Single Data

  1. Navigate to the form.
  2. Click the Edit Form button.
  3. In the Options tab, enable Single Data.
  4. Provide a Qualifier in JSON format.

Qualifier

The Qualifier defines the conditions used to check whether a record already exists.

Examples

1. One record per user

{ "$_.email": $user$.email }

2. One record per user per year

{ "$_.email": $user$.email, "$.year": new Date().getFullYear() }

3. Using $prev$ as a qualifier
If you want to tie a record strictly to a specific previous entry's ID:

{ "$prev$.$id": 12, "$.email": $user$.email }

Note: If an entry doesn't exist, a new entry will be created with previous data automatically mapping to $prev$.$id = 12.

Usage Notes
  • Applies only to special facets: edit-single and view-single.
  • Equivalent behavior can be achieved by using edit with a qualifier parameter: /form/2123/edit?$_.email={{$user$.email}}

1.2 Previous/Next Form

Overview
This establishes parent-child relationships between form entries in a relational approach.

  • One entry can only have one previous form to prevent the diamond problem (cyclic dependency).

Data Entry Behavior

  • Data for the current form can only be added in the context of a previous form’s data.
  • The previous entry’s ID is mandatory to save the current form’s data.

Route for Adding Data

/form/<current-form-id>/prev?entryId=<id-of-previous-data>

You can also use parameters to identify the previous entry dynamically:

/form/<current-form-id>/prev?$.ic=901021...

Dataset & UI Behavior

Dataset of a next form included in the current form automatically links using $prev$.$id = $.$id and filters by the prev data ID.

Warning

If the dataset requires additional parameters, "$prev$.$id": $.$id must be explicitly added in source init parameters.

1.3 Facets

Overview
A Facet controls the state of fields (edit, view, disabled, hidden, none).

Usage & Scripts

  • You can open a form with a facet by passing the facet key in the URL: /form/<form-id>/<facet-key>?entryId=<entryId>
  • In your scripts, you can check the current facet state using the $action$ variable.

1.4 Extended Form

Overview
An Extended Form inherits all items from the original form but allows you to rearrange, add, or remove items.

  • Use Facet when: Differences are only in field states or minor script/validation variations.
  • Use Extended Form when: The form structure/layout changes entirely or requires significantly different lifecycle/validation scripts.

1.5 Form Lifecycle & Items Control

A form provides several lifecycle events where you can run custom scripts. For multiline statements, always wrap the code in an IIFE (Immediately Invoked Function Expression).

Lifecycle Trigger Description
Init Function onInit() Runs on load.
On Save onSave() Runs after entry data is saved.
On Submit onSubmit() Runs after the entry data is submitted.
On View onView() Runs when the entry is opened in view mode.

Example: Reusing Init code in On View

(function(){
    $this$.isView = true;
    onInit(); // Call function directly to trigger outside of lifecycle
})()

Items Control (Field Behaviours)

  • Post-action: Triggered automatically when the field value changes.
  • Pre-requisite: Runs continuously on "ticks". It must return a truthy or falsy value to determine if the field is included/visible.

1.6 Pre-requisite

To get a value from a Normal Section as a pre-requisite value in a Child Section:

$_.data.mod_staf.code == "PA"

1.7 Evaluated Fields (EF) & Bindings

  • Bindings: Evaluated in real-time on the client-side and run on continuous "ticks".
  • Evaluated Fields (EF): The value for an EF is whatever is returned by the expression. Like lifecycle scripts, use an IIFE for multiline statements, and it must return a value.
  • PDF Exports: Use html-keepvalue in your markup if the evaluated value is needed during a PDF export.
  • Backend-EF (B-EF): Use B-EF to update prior data based on a newly evaluated field on the server side.

2. Dataset

2.1 Custom Query Builder

The Custom Query Builder allows you to define advanced, nested conditions for dataset queries using JSON. This gives you more flexibility than simple parameters.

  • The outermost condition is controlled by @cond (default: AND).
  • You can combine conditions using $and and $or, or by specifying parameter keys directly.

Steps to Add a Custom Query Builder

  1. Navigate to UI Editor > Datasets.
  2. Select the dataset you want to edit.
  3. Click the Edit Dataset button.
  4. In the Edit Dataset modal dialog, go to the Filters tab.
  5. Under Custom Query Builder, enter your query JSON.
  6. Click Save List.

Query Builder Rules

  • Keys can be:
    • $and → logical AND (accepts an array of conditions)
    • $or → logical OR (accepts an array of conditions)
    • A parameter key (e.g., $.name~contain)
  • Parameter keys in the query builder must match the dataset parameters, including decorators.
  • Each condition ($and, $or, or parameter) must be wrapped in its own object.
  • Outermost clause, value of $and and value for $or must be an array.

Example #1: Query Builder

[
  {
    "$and": [
      { "$.age~between": "" },
      { "$.gender.code": "M" }
    ]
  },
  {
    "$or": [
      { "$.email": "{{$user$.email}}" },
      { "$_.email": "{{$user$.email}}" }
    ]
  }
]

Parameter Value Resolution

In the Query Builder, a property’s value is only used if no parameter value or preset filter value is provided. If you know a parameter will always be supplied (via request or preset filter), you can safely set its value in the Query Builder to "" (empty string) or null.

Example #2: Passing values via HTTP request

?datasetId=222&$.age~between=12,50

(No need to pass $.gender.code, $.email, or $_email if already defined in the Custom Query Builder).

Example #3: Passing values via source init or _entry.dataset

{
  "$.age~between": "12,50"
}

2.2 Decorator Reference

Parameter Decorators modify how a query checks a field. Below is the mapping of field types to their available decorators.

Field type Available decorators
Lookup ~in, ~notin, ~contain, ~notcontain, ~from, ~to, ~between
Date, Number, Scale, ScaleTo5, ScaleTo10 ~from, ~to, ~between
Text ~in, ~notin, ~contain, ~notcontain

Parameter Decorators

Decorator Description Example Result
~in Field value is in provided list $.country.code~in="ID,MY,PH,SG" Country is one of ID, MY, PH, SG
~notin Field value not in list $.country.code~notin="ID,MY,PH,SG" Country is not ID, MY, PH, SG
~contain Field value contains string $.name~contain="Mohd" Name contains "Mohd"
~notcontain Field value does not contain string $.name~notcontain="Bill" Name does not contain "Bill"
~from Field value ≥ given number $.age~from=12 Age ≥ 12
~to Field value ≤ given number $.age~to=50 Age ≤ 50
~between Field value between two numbers $.age~between="12,50" Age between 12 and 50

Special Parameter Values

Value Description Example Result
~null Field value is NULL $.gender="~null" Gender is null
~notnull Field value is not NULL $.gender="~notnull" Gender is not null
$now$ Current timestamp $.timestamp~to="$now$" Entry timestamp ≤ now
$todayStart$ Today at 00:00 $.timestamp~to="$todayStart$" Entry timestamp ≤ today start
$todayEnd$ Today at 23:59:59 $.timestamp~to="$todayEnd$" Entry timestamp ≤ today end
Note

Filters configured via Edit Dataset → Filters do not include decorators by default (except for numeric fields). If a decorator is required, you can manually edit the key in the Preset Conditions section to add the appropriate decorator.

2.3 Intersection Query

The ~in operator handles array/list intersections. This is particularly useful when querying child collections or repeating fields. It allows you to match records that contain at least one overlapping value within a list or multi-valued field.

Example Data:

Entry 1: { "data": { "categories": [ { "code": "A" }, { "code": "B" } ] } }
Entry 2: { "data": { "categories": [ { "code": "B" } ] } }
Entry 3: { "data": { "categories": [ { "code": "A" }, { "code": "C" } ] } }
Entry 4: { "data": { "categories": [ { "code": "B" }, { "code": "C" } ] } }

Query:

$.categories*.code~in=A,C

Query Explanation:

  • $.categories* Iterates over all elements in the categories list.
  • .code Targets the code field of each category.
  • ~in=A,C Matches entries where any code value intersects with the set {A, C}.

Result:

The query returns entries whose categories list contains at least one matching code (A or C):

  • Entry 1 (A, B)
  • Entry 2 (B)
  • Entry 3 (A, C)
  • Entry 4 (B, C)

2.4 Filters, Preset Filters & Parameters

  • Precedence if conflict: Parameter > Preset Filter > List Filter
  • To structure a complex query, use the custom query builder.

Example:

[
  {
    "$or": [
      { "$.members*.email": "" },
      { "$.secretariat*.email": "" }
    ]
  },
  {
    "$.status": "active"
  }
]

2.5 Bulk Operations

Handling Selected Entries with $selected$:
When configuring a custom bulk action for a dataset, you can access the $selected$ object, which contains all the entries explicitly selected by the user in the UI.

The $selected$ object is structured as a dictionary (key-value mapping) where the key is the entry ID and the value is the entry data wrapper:

{
   '652010': { id: 652010, data: { /* data object */ } },
   '652011': { id: 652011, data: { /* data object */ } },
   '652018': { id: 652018, data: { /* data object */ } }
}

Example 1: Update all selected entries
To update a specific field (e.g., setting selesai to true) for all selected entries, iterate through the object keys and use the $update$ function.

(function(){
  Object.keys($selected$).forEach(id => {
     $update$(id, { selesai: true });
  });
})()

Example 2: Conditionally update selected entries
If you need to check a value before updating (e.g., only update if type is 'pelajar'), iterate through the object values to access the inner data payload.

(function(){
  Object.values($selected$).forEach(entry => {
     // Only update if the type is 'pelajar'
     if (entry.data?.type == 'pelajar') {
        $update$(entry.id, { selesai: true });
     }
  });
})()

2.6 Dataset Endpoints & Query Syntax

You can query dataset endpoints directly via URL parameters.

  • Standard Query: Add parameters using the usual $.field-code.
    .../list?datasetId=1168&$.city.code=KCH
  • Range Queries: Use decorators for number/date/scale.
    .../list?datasetId=1168&$.age~between=10,16
  • Array/Child Queries: Use * to query within multiple options.
    .../list?datasetId=116&$.joblist*.company=SACOFA
  • Permissive Query (OR): By default, query params are restrictive (AND). Add @cond=OR for any-match.
    .../list?datasetId=116&$.type.code=Stud&$.company=SACOFA&@cond=OR
  • Sorting: Use the sorts parameter.
    .../list?datasetId=116&sorts=$.birthdate~desc,$.name~asc

3. Dashboard

3.1 Advanced Charting: Multi-Category vs. Multi-Value

Understanding the distinction between configurations will help you choose the right visualization.

  • Multi-Category Charts: Segments a single numerical metric by two or more descriptive attributes (e.g., clustered groupings in Bar charts, multi-pie grids in Pie charts). Drill-Down is disabled.
  • Multi-Value Charts: Tracks multiple distinct numerical calculations against a single category axis (e.g., plotting Total Revenue vs Operating Costs on a Dual Y-Axis). Drill-Down is disabled.
Tip

If your primary goal is to allow users to click into a chart and view the underlying raw data (Drill-Down), stick to a Standard Chart (one category, one value).

3.2 Understanding Axes and Series

  • X-Axis (xAxis): The horizontal axis (Categories).
  • Y-Axis (yAxis): The vertical axis (Values).
  • Series: The actual data plotted (bars, lines, pie slices).

3.3 Customizing Charts with ECharts Options

Add native ECharts options in Options > Additional options for chart. REKA will merge (and overwrite) your provided options with the defaults.

Example: Adding a DataZoom Scrollbar

{   
  "series": [{ "name": "Bilangan Peserta" }],
  "dataZoom": [ 
    { "type": "inside", "start": 50, "end": 100 },
    { "show": true, "type": "slider", "y": "90%", "start": 50, "end": 100 }
  ]
}

3.4 Transforming Chart Data

You can modify datasets before rendering using Options > Transform Function.
For quick category or value mapping, use the built-in $eachName$ and $eachValue$ shortcuts:

  • Rename categories: $eachName$(i => 'Zone ' + i)
  • Transform values: $eachValue$(i => i * 5)

Full Script Transformation:
Data for multi-value/category charts arrives as a multi-dimensional array (matrix). Ensure your script iterates rows and columns appropriately.

(function(){
  let remapData = [...$dataset$]; 
  if (remapData.length > 0) {
    // 1. Fix header row
    remapData[0] = remapData[0].map(h => h === 'n/a' ? "No Data" : h);
    // 2. Fix category column
    for (let i = 1; i < remapData.length; i++) {
      if (remapData[i][0] === 'n/a') remapData[i][0] = "No Data";
    }
  }
  return remapData;
})()

3.5 Restful Source Charts

Charts can be generated using data from restful endpoints instead of standard datasets. Ensure the endpoint returns data in the correct JSON array structure expected by the charting engine.

3.6 Enable Drill-Down List

To enable drill-down capabilities for a chart:

  1. Go to Options > Enable Drill-down.
  2. Select Columns: Choose the columns to display (limited to fields from a normal section).
  3. View Entry Button: Check 'Enable Drill-down View Entry' to allow users to open the full record.
Warning

Drill-down will not work for Multi-category or Multi-value charts, as these visualize aggregated data intersections rather than a single database row.

3.7 Chart Parameters & Decorators

Just like Datasets, Charts in REKA also support the use of decorators (~decorator) in their parameters to dynamically filter the underlying data before it is visualized.

This means you can apply the exact same parameter decorators—such as ~in, ~notin, ~contain, ~from, ~to, and ~between—directly to a chart's data source query.

Example Usage:
If you want a chart to only render data for specific categories (e.g., filtering a chart to only show the IT and HR departments), you can pass a parameter to the chart like so:
$.department~in=IT,HR

Note

For a complete list of available decorators and how they function, please refer back to the 2.2 Decorator Reference in the Dataset section.

4. Lambda & Real-time in REKA

4.1 Overview

Lambda is a script runner in REKA that executes on the backend using JavaScript and polyglot Java API access.

  • Lambdas execute on separate threads, making them ideal for long-running processes.
  • A Lambda can only access data within its own app.

4.2 Development & Default Objects

Each Lambda automatically provides access to the following objects:

Object Description
_request Represents the HTTP request object.
_response Represents the HTTP response object.
_out Used for building JSON responses. Example: _out.put("key", value);
_param Provides access to request parameters.
Tip

Always prefer _param instead of _request.getParameter(). _param works consistently whether the Lambda is triggered by a standard HTTP request or by a Cogna function call.

Handling Request Bodies

To get the raw request body in a Lambda (such as from a POST request), use _param._body. This will return a string. To convert it into a usable JSON object, you should parse it:

var requestData = JSON.parse(_param._body);

Available Endpoints generated by Lambda

Endpoint Type Description
Endpoint Returns JSON (_out.put(key, value))
Print / Print PDF Returns text/PDF from print()
Stream Streaming output for long-running processes
Web Viewer Opens output in UI viewer.

4.3 Common Use Cases for Lambda

  1. Scheduled Jobs: Run tasks automatically (cron-like).
  2. API Integrations: Use _http.GET and _http.POST.
  3. Data Validation: Run custom rules before entry saves.
  4. Cogna Integration: Register Lambda as an AI tool.

4.4 Web Scraping with Lambda (Jsoup)

Use the _jsoup binding for web scraping and HTML parsing. It provides DOM traversal using CSS selectors natively on the backend.

var doc = _jsoup.connect("https://en.wikipedia.org/").get();
doc.select("#mp-itn b a").forEach(h => print(h.text()));

5. Real-time Notification

REKA supports multiplexed connections using WebSockets to establish real-time pub/sub communication between clients.

5.1 Client-Side (UI) Usage

  • Available in both Forms and Custom Screens.
  • Subscribe: $live$.watch('channel-name', callback)
  • Broadcast: $live$.publish('channel-name', payload)
Warning

Ensure that your channel is unique to prevent unintended conflicts with other applications or environments. It is highly advisable to include the App ID in the channel key (e.g., channel_update_${$app$.id}).

5.2 Backend (Lambda) Usage

$live$ is also available in Lambda using the _live object. But first, you have to include Live in the Lambda Bindings configuration.

Then, use _live.publish to publish a live notification from Lambda to the listening client (usually a form or screen using $live$).

Lambda Script Example:

// ensure to stringify the message before publish. 
_live.publish(['updated-ticket-info-' + entryId], JSON.stringify(updatedTicket));

Client Listener Example:
On the listening client, parse it back to an object using JSON.parse().

$live$.watch(['updated-ticket-info-' + $.$id], res => {
    let parseObj = JSON.parse(res);
    // Assign to local variable or scope
    $_ = parseObj;
});

6. Integrations & Endpoints

6.1 Enabling a Custom Domain

You can use a reverse proxy to route traffic from a custom domain (e.g., app.example.com) to your REKA subdomain app-path.ireka.my.

Apache (.htaccess)

Requires mod_proxy and mod_headers.

<IfModule mod_rewrite.c>    
    RewriteEngine On    
    # Forward the original host expected by the Reka platform    
    <IfModule mod_headers.c>        
        RequestHeader set Host "app-path.ireka.my"    
    </IfModule>    
    # Reverse proxy all requests to the Reka application    
    RewriteRule ^(.*)$ https://app-path.ireka.my/$1 [P,L]
</IfModule>

Nginx

Use proxy_pass and proxy_set_header Host in your server block.

server {    
    listen 443 ssl;    
    server_name mydomain.com;    
    location / {        
        proxy_pass https://app-path.ireka.my/;        
        proxy_set_header Host app-path.ireka.my;        
        proxy_set_header X-Real-IP $remote_addr;        
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        
        proxy_ssl_server_name on;    
    }
}

6.2 Telegram Bot Setup x Reka

Use @BotFather on Telegram.

  1. Run /newbot
  2. Set the Name and unique Username (must end in bot).
  3. Obtain the token format <bot_id>:<secret_token> for webhooks.

6.3 Integrating REKA into Mobile Apps (WebView)

Embed specific components (Forms/Dashboards) via native WebView wrappers.

Requirements

Enable the following on your mobile WebView client:

  • File Upload: Needed for attachments.
  • Camera Access: Needed for capture fields.
  • Geolocation: Needed for location fields.
  • Service Workers: Needed for PWA/offline caching.

Authentication

Append tokens to the URL parameters to authenticate the WebView session natively:

  • ?accessToken=X&provider=Y
  • ?apiKey=Z (For system/kiosk level access)

Android (WebView) Example

WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setAllowFileAccess(true);
settings.setAllowContentAccess(true);
settings.setMediaPlaybackRequiresUserGesture(false);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("https://hr-system.ireka.my/?apiKey=abc123xyz");

iOS (WKWebView) Example

let config = WKWebViewConfiguration()
config.preferences.javaScriptEnabled = true
config.websiteDataStore = .default()
let webView = WKWebView(frame: view.bounds, configuration: config)
view.addSubview(webView)
let url = URL(string: "https://hr-system.ireka.my/?accessToken=XXXX&provider=google")!
webView.load(URLRequest(url: url))

6.4 3rd Party Integration Methods

  • Backend Data (Inbound/Outbound): Achieved via Restful API using $http$, $endpoint$, or custom Lambda functions.
  • Frontend Library Integration: External JS libraries can be injected directly into forms/screens using the $loadjs$ utility.
  • Tooling (Reporting/Analytics): Can consume data from dataset endpoints, chart endpoints, or custom Lambdas.

6.5 External Endpoints Manager

Use the Endpoint Manager to register and securely manage external API endpoints centrally.

  • Authentication: Native support for OAuth2 flows.
  • Execution: Can be called via $endpoint$ on the frontend or _endpoint in Lambda.
  • Parameters: URL parameters can be unboxed dynamically using placeholders {} populated by a provided JSON object payload.

File Blob / Byte Array Handling

If an external endpoint returns a file (blob), set the configuration to Response Type: Byte Array to prevent file corruption.

  • Frontend: Convert the byte array to a file object using blob:base64.
  • Lambda: Write the byte array directly to the response output stream:
var out = _response.getOutputStream();
out.write(byteArray);

7. Lookups

7.1 Database vs Restful Lookups

REKA allows fields to pull data from either internal Database Lookups or external Restful API Lookups. Each requires specific configurations for data mapping.

Restful Lookup Configuration

  • Endpoint URL: Supports placeholders {} that are dynamically unboxed with values passed via parameters.
  • Root: Points to the specific JSON path that contains the array or list of data to be iterated.
  • Code, Name, Extra: Points to the specific JSON paths for these respective values (this path should be relative to, or excluding, the Root path).

Additional Data Fields

How additional data is handled depends on the type of lookup being used:

Lookup-Database:

  • You must specify additional fields as a schema.
  • To specify the data type, use the format: field_name:type
  • Supported types: text, longtext, number, date, file, options, lookup.

Lookup-Restful:

  • You can leave the schema configuration blank to automatically include all remaining JSON fields as additional data.
  • To explicitly remap, rename, or flatten deep JSON fields, use the @ syntax.

General Syntax to Map Fields

Whether remapping a Restful lookup or structuring a Database lookup, use the following general syntax:

field_name:type@/path/to/value

7.2 Lookup Query Endpoints

You can pass parameters directly into Lookup Query Endpoints to filter lists.

  • Database Lookup: .../lookup/5108/entry?extra=Staff&$.gender=Male (Can be filtered using Code, Name, Extra, or $.<additional-field>).
  • Restful Lookup: Only supports parameters specifically supported by the source API endpoint.

If a Restful lookup requires a POST request with parameters in the body, pass a postBody array literal:

{
  "postBody": [{"paramName": "co_id", "paramValue": $.cp_course_id.extra}]
}

8. REKA Templating & Screens

8.1 Formatting Pipes

REKA provides formatting pipes ({{val|pipe}}) to transform data directly on the view before rendering.

Pipe Usage Description / Format
{{$.date_field|date:"DD-MM-YYYY"}} Custom Date string formatting.
{{$.attachment|src:inline}} Inline display (Streamable video/audio: src:stream)
{{$.filing_no|qr}} Generates base64 QR Code image source.
{{$.amount|number:"1.2-3"}} Number format: minInt.minFrac-maxFrac

8.2 Mailer Templating

The Mailer module uses StringTemplate (ST) v4 engine. It supports array iteration ({{ $.userlist:{user | ...} }}) and conditional logic ({{if (...)}} ... {{endif}}).

Field Formatters (Inline Transformations)

Formatter syntax Description
{{$.date;format="date:dd/MM/yyyy HH:mm"}} Date formatter
{{$.number;format="number:%32.12f"}} Number formatter (Uses Java String Formatter)
{{$.text;format="string:upper"}} Make uppercase
{{$.text;format="string:lower"}} Make lowercase
{{$.text;format="string:cap"}} Make first-cap
{{$.text;format="string:url-encode"}} Encode URL
{{$.text;format="string:xml-encode"}} Encode XML
{{$.file;format="src"}} Upload file URL
{{$.file;format="qr"}} QR image src

Triggering Mailer via Lambda

// Direct Payload formulation
_mail.send({ to: "...", subject: "...", content: "..." }, _this);

// Pre-defined Template mapping
_mail.sendWithTemplate("mailer-id", entry_data, _this);

8.3 Custom Screens

Custom screens allow you to build completely bespoke interfaces inside the REKA app shell wrapper.

  • Capabilities: Supports native plugins like the QR scanner integration.
  • Scripting Scope: Logic can be scoped to the Entry Page context, Entry List, or global Static Page contexts depending on the screen type selected.

9. App Structure & Global Variables

9.1 Global $conf$ Object

$conf$ is a state object used to declare app-scoped global variables that persist throughout the user session.

  • The values stored in $conf$ are accessible across all components, such as forms, datasets, and custom screens.
  • To initialize and declare values for $conf$ immediately when the app starts, place your logic inside the Structure Init Function.
// Example in Structure Init
$conf$.deptCode = "HR_01";

Async Initialization & Change Detection

The App Structure Init function also supports asynchronous operations. This is highly useful when you need to fetch global data (like user profiles or lookup dictionaries) via API before rendering dependent UI components.

Example:

(async function(){
  let profileRes = await $web$.get('https://io.ireka.my/api/entry/by-params?formId=5473', {
    params:{
      '$.email': $user$.email
    }  
  });

  $conf$.profile = profileRes.data;
  $digest$();
})()
Important Notes
  • Note the keyword async in the IIFE (Immediately Invoked Function Expression) and the use of await for the $web$.get request.
  • If the value of $conf$.profile (or any asynchronously fetched global variable) is used directly in the UI template, it is a good idea to call $digest$() after setting the value to ensure the change detection is fired up and the interface updates immediately.