JavaScript API's for AppWorks platform client operations

Options
nssmani
nssmani E mod
edited May 29, 2023 in Articles #1

The new JavaScript client API’s on AppWorks client can be used for developing custom pages/navigation as per the need of the application. Till now any custom logic written outside and embedded in the AppWorks client (as XForm or HTML page in a Webcontent panel) doesn’t have a tighter integration which requires a hard refresh of client to see the updates. Now with the new API’s, custom pages can communicate with AppWorks client to read/update an entity instance details and also allows you to perform navigation and actions from outside the AppWorks client.

These client API provides easy access to Entity data available in AppWorks client and navigation across multiple items/layouts through API's

  • Navigation across different layouts
  • Read data or relation of an Entity instance
  • Update the data of an Entity instance
  • Save the data of an Entity instance
  • Perform Action on an Entity instance

Note: The JavaScript APIs use the Promise syntax for returning values. For more information see Promise syntax and its usage.

Navigation across different layouts

The API navigate() is used to navigate to a specific Item instance or a Home layout.

publicAPIProvider.navigate(ID,
{"layoutId": 'layoutID', "clearBreadcrumb": true, "breadcrumbName":'newName'})

Parameters description

+------------------+-----------------------------------------------------------------+
| Name             | Description                                                     |
+------------------+-----------------------------------------------------------------+
| ID               | Mandatory.                                                      |
|                  | ID of the Homepage layout or the Item to navigate.              |
+------------------+-----------------------------------------------------------------+
| layoutId         | Optional.                                                       |
|                  | Layout ID of the item to navigate when its an Item to navigate. |
+------------------+-----------------------------------------------------------------+
| clearBreadcrumb  | Optional.                                                       |
|                  | Boolean. Clears the existing breadcrumb when 'true'.            |
+------------------+-----------------------------------------------------------------+
| breadcrumbName   | Optional.                                                       |
|                  | Name of the breadcrumb to populate when navigated to a new page.|
+------------------+-----------------------------------------------------------------+

Return Value

The API returns a promise and upon fulfilling the promise, values are returned. Boolean, 'true' when the navigation is successful.

Example:

When you load your custom html in a Webcontent panel, you can use the API as below.

window.parent.publicAPIProvider.navigate(itemID,{'clearBreadcrumb':false,'breadcrumbName':'Seat selection', 'layoutId':'<ID of layout>'});

Read data or relation of an Entity instance

The API getItemData() is used to obtain an item's details such as properties and relationships for the itemID.

You can also use this API to get the latest data to client data when the data is updated in the background.

publicAPIProvider.getItemData(itemID, {"refresh":true,"relationName":"Name"});

Parameters description

+------------------+------------------------------------------------------------------------+
| Name             | Description                                                            |
+------------------+------------------------------------------------------------------------+
| itemID           | Mandatory.                                                             |
|                  | Item ID of the Entity instance.                                        |
+------------------+------------------------------------------------------------------------+
| refresh          | Optional.                                                              |
|                  | Boolean. When set to 'true', details are always                        |
|                  | retrieved from the server.                                             |
+------------------+------------------------------------------------------------------------+
| relationName     | Optional.                                                              |
|                  | Name of the required relationship.                                     |
+------------------+------------------------------------------------------------------------+

Return Value

The API returns a promise and upon fulfilling the promise, values are returned. Item object when a valid item is available.

Example:

When you load your custom html in a Webcontent panel, you can use the API as below.

  window.parent.publicAPIProvider.getItemData(itemID).then((itemData) => {
	// Your custom logic and itemData has the details
  });

Update the data of an Entity instance

The API updateData() is used to update the data related to particular instance.

publicAPIProvider.updateData(itemID, propertyName, propertyValue)

Parameters description

+------------------+------------------------------------------------------------------------+
| Name             | Description                                                            |
+------------------+------------------------------------------------------------------------+
| itemID           | Mandatory.                                                             |
|                  | Item ID of the Entity instance.                                        |
+------------------+------------------------------------------------------------------------+
| propertyName     | Mandatory.                                                             |
|                  | Name of the property as defined in design.                             |
+------------------+------------------------------------------------------------------------+
| propertyValue    | Mandatory.                                                             |
|                  | Value of the property            .                                     |
+------------------+------------------------------------------------------------------------+

Return Value

The API returns a promise and upon fulfilling the promise values are returned. Boolean, 'true' when the update is successful.

Example:

When you load your custom html in a Webcontent panel, you can use the API as below.

window.parent.publicAPIProvider.updateData(itemID, '<property name>', '<property value>');

Save the data of an Entity instance

The API saveAllItems() is used to save the data of all items.

publicAPIProvider.saveAllItems()

Return Value

The API returns a promise and upon fulfilling the promise no values are returned.

Example:

When you load your custom html in a Webcontent panel, you can use the API as below.

window.parent.publicAPIProvider.saveAllItems();

Perform Action on an Entity instance

The API performAction()is used to trigger action on an Entity instance.

publicAPIProvider.performAction(itemID, actionName)

Parameters description

+------------------+------------------------------------------------------------------------+
| Name             | Description                                                            |
+------------------+------------------------------------------------------------------------+
| itemID           | Mandatory.                                                             |
|                  | Item ID of the Entity instance.                                        |
+------------------+------------------------------------------------------------------------+
| actionName       | Mandatory.                                                             |
|                  | Name of the action to be performed.                                    |
+------------------+------------------------------------------------------------------------+

Return Value

The API returns a promise and upon fulfilling the promise values are returned. Boolean, 'true' when the action is successful.

Example:

When you load your custom html in a Webcontent panel, you can use the API as below.

window.parent.publicAPIProvider.performAction(itemID, '<action name>');

Happy development using of new client JavaScript API' for building better integrations in your Application 😊

Comments

  • Antal Bos
    edited October 20, 2021 #2
    Options

    You are my savior! I already asked several OT people for a clearer example and now I just see it's publicly described within this post!? Why isn't this information available in the regular documentation...Great stuff by the way to play around with it next week-end...thx

    Also have a look at this post 🤩

    Grz, Antal

  • Antal Bos
    edited October 20, 2021 #3
    Options

    Before I forget....It would be great to add a small example HTML file as attachment for a final conclusion. This way we have a practical example to learn from and might see some best practices we can use at our customers.

    Just a basic skeleton HTML would be sufficient, so we see what JS libs and CSS files are included for a seamless AppWorks runtime HTML customization.

    Thx, Antal

  • nssmani
    Options

    @HetBenkt , These new API's are available in 21.4 and regular documentation for the API's is also available in ADVANCED DEVELOPMENT > Application development (How Tos) > Using the application JavaScript APIs. We will work on the examples soon and add a reference here.

    Thanks for the nice 21.4 overview page. Looks great and covers all the features.

  • NICEEEEE!! :)

    Good job...You will make a lot of customers happy!


  • nssmani
    Options

    @HetBenkt , Yes. They are very powerful and simple as above to use 😉

  • @nssmani thank you for the demo yesterday...Was very helpful. Coming back to my question on calling the publicAPIProvider from outside the appworks runtime. Have a look at the sample html file which is deployed on the TomEE server via a web library definition. So, I'm able to access it via this URL: http://<host>:<port>/home/<org_name>/html/playground_external.htm, but I end up with a undefined publicAPIProvider. I already included all other platform JS files, but still the same issue. So, it's looks like I first need to initialize something, but I don't know how? I also make a session before accessing this file, so my JavaScript libraries are loaded without a 302-error in the network console.

    This is the final stacktrace:

    "ReferenceError: publicAPIProvider is not defined at HTMLDocument.<anonymous> (http://<host>:<port>/home/<org_name>/html/playground_external.htm?itemid=080027e84f06a1ec8deeaa8dab74a43a.1:12:9) at mightThrow (http://<host>:<port>/cordys/thirdparty/jquery/jquery.debug.js:3762:29) at process (http://<host>:<port>/cordys/thirdparty/jquery/jquery.debug.js:3830:12)"


  • nssmani
    Options

    @HetBenkt, When you call from external page which is outside AppWorks client you need to wait for the AppWorks client to complete its loading and call the publicAPIProvide on the AppWorks Frame like below.

    let intervalID = window.setInterval(() => {
        let appworksFrame = document.getElementById('appworks_frame').contentWindow;
        if (appworksFrame) {
            if (appworksFrame.publicAPIProvider && appworksFrame.publicAPIProvider.updateData) {
                appworksFrame.publicAPIProvider.updateData('080027e84f06a1ec8deeaa8dab74a43a.1', 'prs_id', 'updated externally!');
                clearInterval(intervalID);
                console.log(`I found the API, Now clear the timer`);
            }
        } else {
            console.log('I cannot found the hook, let this timer run again');
        }
    }, 200); 
    

    This is what i have done in the above code

    • Wait for the loading of AppWorks client using a timer. This is required only for first load. Once AppWorks client is loaded you can call the API's directly.
    • Call the API on the appWorksFrame. Hear 'appworks_frame' is the Id of the frame in which the client is loaded.
    • Clear the timer once the API's are available.

    Try replacing the code in your test page and if you still find it difficult i can provide a sample page.

  • @nssmani I'm getting closer and the object is indeed defined with a value now and my updateData() with saveAllItems() is done, but I don't see the value being updated eventually in the iframe. That's also not the case when I have a look in the regular runtime in another browser tab?

    Thx, Antal


  • @nssmani after wrapping it behind a button click it works smoothly!


  • @nssmani

    Here you see my toMany relations in the dev-console are empty on the parent 'Game' entity, but clearly available in the normal UI. Only the toOne relation is available as itemId to continue with.

    Grz, Antal

  • @nssmani

    It's strange behavior. A refresh of the page provides me with differences after each refresh?

    This time the related Users are retrieves:

    A second refresh they are empty again:

    Gr, Antal

  • nssmani
    Options

    @HetBenkt , Can you please share a sample project to check?

  • @nssmani It looks like a timing issue as my 'Decks' are also not loaded at that moment in time. Maybe you have an advise on how to first load all the rest and finally load my centered html page.


  • This is not working; It's still an empty array (the Deck's are fully loaded in the UI), so it's a level deeper...I guess?

    $(document).ready(function(){
       setTimeout(function(){
             //YOUR CODE
       },4000);
    });
    
  • nssmani
    nssmani E mod
    edited January 11, 2022 #16
    Options

    @HetBenkt , ToMany peer type relationships are not loaded as part of the original item and will be requested only when displayed in the UI. If you need ToMany peer relationship you can request for it and will be added to the item. See below where ToSkills is a ToMany peer type relation which is not available initially but will be added on request.


  • @nssmani

    Hey Mani,

    Would it be possible to also have some kind of 'listener' available within this API?

    So, when the entity is updated in the back-end by another user's UI, you are notified somehow in the Promise object under you own account's UI?

    Thx, Antal

  • @nssmani

    Another question: Can I also perform an action rule which triggers a BPM and sends back the BPM output message data as a result of the Promise? Instead of only sending back a success Boolean value.

    Thx, Antal

  • nssmani
    Options

    @HetBenkt , AppWorks loads the data when opening the respective list/Item details and doesn't poll to runtime to get any updates. Users need to navigate back to the page or refresh the browser to get the latest details. You can implement poling in your custom page by calling this read item details API as per your requirement but keep an eye on the performance impact.

    Can I also perform an action rule which triggers a BPM and sends back the BPM output message data as a result of the Promise

    In Entity modelling you can get data only using an item reference. For above you can save the BPM output to a temporary property and read the item data after the action rule is executed successfully.

  • @nssmani @nking

    Hereby the challenge sources; for you to validate.

    Have fun! 😉