Application Packaging Standard

Last updated 18-Mar-2019

Single Page Application

In this document:

Environment

An APS application should use single page views in UX1. The key differences of this technique are as follows.

  • To be available in the reseller, customer, or service user environment, the application navigation tree must plug into the respective placeholder, for example:

    <navigation id="vps-mgmt" label="VPS Management">
        <plugs-to id="http://www.parallels.com/ccp/2"/>
        <view id="servers" label="Servers" src="ui/servers.js">
         ...
    </navigation>
    

    Note

    For a file with the *.js name extension (unlike .html), the src attribute must be specified explicitly.

  • In the ui/ folder, the bootstrapApp.html file must exist. The file is loaded in an IFrame the first time one of the application views is open. Here is its contents:

    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8">
       <script>
    	// On the client side, window.location.href provides the path to the page
         var url = window.location.href.split('/');
         window.dojoConfig = {
           packages: [
             {name: 'app', location: url.slice(0, -1).join('/')},
             {name: 'pacs', location: url.slice(0, -3).join('/')}
           ]
         };
       </script>
    
       <script type="text/javascript" src="/aps/2/ui/runtime/client/aps/aps.js"></script>
       <script>
            require([
               "aps/load",
               "aps/ready!"
            ], function(load){
                 load(["aps/PageContainer"], "aps-frame");
            });
       </script>
    </head>
    <body>
       <div id="aps-frame" class="ccp-content-body"></div>
    </body>
    </html>
    

    Note

    When building an APS package by means of the aps build utility, the latter adds the bootstrapApp.html file if it does not exist in ui/ and at least one element with src="*.js" is declared inside the navigation tree plugged into UX1.

  • When a user switches to another view from the current view, the latter will not be removed from the IFrame. All its embedded widgets are still available in the IFrame.

    Warning

    For this reason, follow the recommendations on assigning widget IDs unique in scope of the whole application, not only in scope of a view.

The following diagram illustrates how it works.

../../../../_images/view-flow.png
  1. In UX1, a user opens the view-11 of the App-1 application.

  2. The system creates an IFrame and loads the bootstrapApp.html file along with the view-11 source code to this IFrame. Since this point, the view-11 code will be in the IFrame even when the user switches to another view.

  3. The user navigates to the view-12 of the same application.

  4. The system loads the view-12 source code to the IFrame. Since this point, all backward and forward transitions (dash lines) between the two views will be inside the IFrame.

  5. The user goes to the view-21 of the App-2 application.

  6. The system creates an IFrame and loads the bootstrapApp.html file along with the view-21 source code to this IFrame. Since this point, the view-21 code will be in the IFrame even when the user switches to another view.

    All subsequent forward and backward steps 7-8 and other in the App-2 UI will be processed similar to the steps explained earlier for App-1.

The system removes IFrames when the user re-login to UX1 or refreshes the browser.

View Structure

Key Features

Compared with the typical structure of a view in CP, there are a number of differences in the structure of a single page view in UX1:

  • The view inherits the aps/View module.

  • The views of an application can share data through the aps.app object. A view can create an object in the aps.app object to share it with other views in the same IFrame. For example, you can share the aps.app.model object between all views of the application.

  • The view inherits a number of flow methods triggered sequentially by UX1 thus implementing a certain life-cycle. Among the flow methods, the init method is called only once to initialize the view, when a user opens it for the first time. The other methods are called each time the the user comes back to the view. The only mandatory method is init.

  • The system loads the widgets of the application views into the root aps/PageContainer defined in the bootstrapApp.html file.

    Warning

    For this reason, do not try to create this container in a view.

Flow Methods

Flow methods of a view follow each other or are called by external events as the following diagram presents:

../../../../_images/method-flow.png

Note

If a notification comes when a popup view is open on the screen, it will not call the onContext method of the view. Instead, after the popup view is closed, the onContext method of the parent view will be called.

The following table briefly explains the flow methods:

METHOD PURPOSE ACTIVATED RETURNS
init
* Declare data sources
* Define and initialize data models for widgets
* Define internal widget handlers, for example, cell renders in a grid
* Initialize page layout as a hierarchy of widgets mapped to data models
Only once, when the view is loaded into the app IFrame by bootstrapApp.html
One of the following:
* Hierarchy of widget definitions (recommended)
* Undefined
onShow Secondary role - for example, prepares widgets before making them visual
* After the widgets returned by init are loaded
* Every time a user returns back to the view
One of the following:
* Deferred promise
* Undefined
onContext
* Get actual data from the data sources
* Update data models
* Update widgets (not required if mapped to a model)
* Show widgets after calling aps.apsc.hideLoading()
* After the onShow promise (if defined) is resolved and the aps.context object is filled with actual data
* A notification is received
Undefined
onHide Reset some variables or widgets before hiding the view
* When the gotoView method is called
* When the user selects another view in UX1
Undefined

Example

Step-by-step demo project illustrates creation of a basic application with single page UI.

init