App Development: User Guide

Introduction to ZOAPIIO Apps

A (near) identical code base for both native web and native mobile applications has been a goal worth pursuing for . The user application development architecture has been developed and built with this goal in mind.

In due course, however, it has become evident that the value addition of the approach to Web user application development has been marginal over conventional methodologies. An implementation as described here does exist for Web applications, but further development for Web user application framework has been stopped.

Only the Mobile application development framework is undergoing regular enhancements and is being fully supported. Mobile apps are Flutter/Dart based - users can consider Flutter-Web for their web applications.

Apps are end-user web and mobile apps built over ZOAPIIO. App development process is optimized over what you may be used to if you have developed front-end or full-stack apps before.

Let us start by looking at the high-level process.

Conventional approach ...

proceeds roughly as follows -

  1. The project effort and hence teams are divided into one each for the admin app, backend, web app, and mobile app. Besides, there are support teams like devops and QA. If you are using native development for Android and iOS, then you need one more team in your project.
  2. The backend team designs and builds the functional APIs using a suitable server-side language or framework.
  3. The front-end design generally starts with UI wireframes using tools like figma.
  4. The front-end development starts by getting a UI structure generated from the wireframe tool and then proceeds to programming the interactivity and server integration.
  5. The backend and front-end development proceeds simultaneously as each of these feedback changes into the other.
  6. After a few sprint-cycles the final app starts to take shape and then refined over a period using the same process.

... is sub-optimal

There are several inefficiencies in the conventional approach that ZOAPIIO addresses, such as-
  1. Conventional approach requires multiple and advanced skill sets. These are expensive and suffer for manpower related problems like hiring, retention, training, and retraining.
  2. Multiple teams require coordination - additional time and effort is used up in managing the touch points.
  3. Larger teams tend to lower overall productivity.
  4. Therehttps://www.apollopharmacy.in/otc/revital-h-woman-tab-30s?doNotTrack=true is limited opportunity for leveraging code generation. It is mostly limited to CRUD on the server-side and initial application skeleton on the client side.
  5. Code generation benefits are available only once at the start of the project. Enhancements must be programmed manually.
  6. Functionality enhancements impact all teams and turnaround time is high because of interdependencies. Further, the overall timelines are determined by the slowest team.

The ZOAPIIO Way

As we will see in the rest of this document, architecture allows you to break away from convention and adopt a fresh approach addressing most of the pain points. The following are the key characteristics of building apps with -

If you have already worked on server-side APIs with , you would observe that the abstraction principle of is nothing but intent based programming. The same principle is extended to front-end Apps.

Server-driven or backend-driven mobile UI is a hot new approach that is gaining traction where the app UI can be updated from the server without having to compile and push the app with every change.

As a bonus, supports this capability natively at no additional programming effort.

Getting Started

The process of building web and mobile apps in is the same. This is because the build process relies heavily on code generation. The difference comes when you start to add custom interactivity - for mobile app, you will use the dart programming language and JavaScript for the web. The programming model is identical for web and mobile and only the underlying language is different - you can replicate the same code with only minor changes to syntax.

Creating the app design is easy because uses function first approach. Your design is simply a skeleton for page layout, the appearance is addressed later. To address the web and mobile deployment targets of your app -

  1. You can create the complete design, clone it and then build interactivity for each app independently, or
  2. If your app for web and mobile is identical, then you can build a single app and add Web/mobile interactivity programming separately in the same app.

Before you proceed

Every technology has its strengths and use case scenario where it shines. While is a generic build and runtime environment for internet-based solutions for web and mobile, its strengths are best leveraged in a commercial business type of application. Before proceeding, consider the following-

  1. A business application is one that has a significant server-side role; there are user transactions, which require monitoring, and perhaps fulfilment and customer service. is ideally suited for this, because it takes an integrated view of the problem and can deliver maximum value.
  2. An application which is heavy on user-interactivity, and has a smaller server-side role, will have limited benefit from the platform.
  3. For applications which have significant server-side role but are also heavy on user interactivity, we advise to use for building the server and server APIs. The front-end should be built using conventional methods (while still using ZOAPIIO services).
  4. The platform offers no advantage to building gaming apps.

Mobile app strategy

The mobile app development landscape today, unfortunately, is fragmented and non-standard. In an ideal world, the web technology, which is already standardized, would work on mobile platforms as well. Bridging solutions exist, but none solves the problem completely - there are trade-offs and choices involved. Before you get down to building the mobile app on ZOAPIIO, take a moment and think about your mobile app needs.

  1. A web-app (written using HTML/JS/CSS) can be compiled for mobile platforms using technologies like Cordova and PhoneGap. However, the resulting application has inferior UI performance compared to the native apps. If your app users are unlikely to be affected by a slight drop in performance, this may be the best option. ZOAPIIO Web app can be compiled using Cordova.
  2. PWA is gaining popularity as an alternative to native apps. See if you can drop the mobile app in favor of the PWA. ZOAPIIO supports PWA as well.
  3. Lastly, ZOAPIIO lets you build your mobile app in platform neutral Flutter SDK. This will require more effort and time compared to other options, but you will get native apps for Android and iOS.
  4. You can also consider starting off with a Cordova wrapped mobile app and delaying full graduation to native.

The admin application

A web or mobile app, without an admin control, is of minimal utility. A large part of business functionality consists of provisioning content and policies for the proper functioning of the app. Some common situations are-

  1. Inventory of goods and services sold for an eCommerce app.
  2. Content and advertisements for social media apps.
  3. Management of third-party contracts for content insourced from suppliers.
  4. CRM - managing user complaints and feedback.
  5. Policies - management control of application behavior.

Think about and document the admin control requirements of your app. You will build the admin application using Wizard and your database design will be a part of it.

More on Mobile

There are some parts of the mobile app development that need to be addressed outside of ZOAPIIO, in your Cordova or Flutter project.

App environment

Before the app is put on the user's screens, it is required to have properly configured icons for different screen resolutions and configurations. The app may also have a splash screen, a visual to fill the short amount of time it takes before your app opens. You must create these as per the recommended procedure for your environment.

Signing and publishing

Both Google and Apple have a process for listing the app in their on-line stores. They will require you to have an account with them, digitally sign the app and have a verification/review process before the app gets listed on the store. You must go through these steps with the respective vendor.

Versions and dependencies

When building your Cordova or Flutter you may encounter errors depending upon the configuration you have used. You could encounter problems related to versions of your libraries, SDKs and dependencies. You will find solutions to these problems through the Internet search. Most are simple to fix, and you will wise up after some experience.

Device ecosystem

Having an app is a great opportunity to interact with the users' devices and other apps on their device. Both Cordova and Flutter provide means of doing this. You should explore such opportunities and incorporate such features in your app.

Design your app

Consider your application as composed of three functional parts-

  1. The pages in the application, their layout, composition, data source and data binding. The pages can also have floating action buttons.
    WebIDE is an integrated IDE for backend and frontend. This allows you to assign data source APIs and individual data-element bindings at design time. System manages the data retrieval and rendering transparently.
  2. Navigation - central control to launch pages.
    The system automatically manages the navigation bars and basic navigation in your application.
    You can, additionally, control the navigation programmatically as well.
  3. Sign-up and registration functionality.
    Sign-in and sign-up functionality is automatically managed for you and is fully configurable.
app is a collection of pages. Each page is a hierachical composition of views .

Get started by documenting, in plain English or by using a diagramming tool, the list of pages in your application and the layout of each.

The list and the layout of your application pages need not be final right away - start with an essential set - this will evolve during the life of the application. As we have already mentioned, the code generation benefits are available throughout the evolutionary life of your application.

The programming model

will create a functioning flutter or HTML/JS application from the app abstraction that you define. The app is started and managed by the runtime. You will complement the basic app with your custom program stubs for-

  1. User Interactivity. You will need to respond to user actions in the app beyond the standard functionality of the input controls. The interactivity handling in the form of responding to events, which you configure with the controls when building the app.
  2. Custom Controls. There may be certain types of input controls that doesn't support out of box. You can provide your own custom controls programmed in HTML/JS and Flutter respectively. Almost all input types are supported natively, so you will require this is advanced cases only.
  3. Styling Overrides. The basic app comes with comprehensive styling controls which should meet your requirements. For mobile apps, additional finer styling control is available by providing custom Flutter code.
  4. Other overrides. You can override the entire rendering of a view with your custom HTML/JS or Flutter code respectively. Default rendering is sufficient for most cases, this is an advanced scenario and is rarely needed.
  5. Computational support. If your app requires specialized computational support, the corresponding JS or Flutter libraries can be included in your project.

Your custom program stubs can access and control the contents of the user screen, and app state, among other things. We will look at the details of the programming later, but before we start the discussion on building the application, let us get an overview of the programming interface you will use to achieve this-

The global $.app Object

In both web and mobile app programming, a global object is available to your program stubs named $.app. This is your handle to access anything in the application. Every action you take in the application programmatically will be a method call on this object.

The app Context

The app context is a global object maintained in $.app which can be used to communicate between your application and the runtime. The object itself is a JavaScript object for Web and of the generic object type Map<String,dynamic> in flutter.

Pages, Views, and Elements

hides the details of internal objects and classes; and exposes the abstracted view of the application. The contents of the pages, views, and elements in the app are accessed using their names. When building the apps, remember to give each view/element a simple and recognizable name.

Events

Web programming uses events to manage user interactivity - HTML elements emit events which can be trapped and then responded to by your JavaScript programs. Flutter however, uses action handlers for the same purpose. When creating a Flutter widget, you specify the functions that should be executed when certain actions occur on the Widget.

To create a common programming model for both Web and Mobile, uses events and maps both environments to the same event-based API. fire and listen methods are used to interact with the event sub-system. See $.app Object Reference.

Event names are generic and you can fire/listen to any event name within your app. The following predefined events are associated with Application-

  1. notification - This event is fired when an in-app notification is received. This is different from the Device Platform notifications. These notifications are generated from within the application.
  2. login - This event is fired when the user completes a login or an existing login is detected.

Following predefined events are associated with Elements-

  1. pressed - This event is fired when an element of type button or submit is pressed or clicked. This is different from click which is fired for other element types.
  2. click - This event is fired when an element of type other than button or submit is pressed or clicked.
  3. change - This event is fired when the user changes the value of an inputtable element.
  4. doubleclick - This event is fired when an element of type other than button or submit is double clicked or double tapped.
  5. mouseover - (Web only) This event is fired when the user moves the mouse over the element.

Following predefined events are associated with Pages/Views-

  1. floatingaction - This event is fired when the Floating Action button on a page is pressed (mobile only).
  2. nav - This event is fired when an entry on the Navigation Bar, which is configured for programmed action, is invoked.
  3. beforeload - This event is fired just before rendering a view. If you handle the event, you can return true/false (a bool value) to indicate if the view should be rendered or not. A falue value will cause the view to be omitted from the page display.
  4. nodata - This event is fired when rendering a List view that has zero records. From your handler of this event, you can return a string which will be displayed to the user in the view. If you do not handle this event, a default message is displayed.

Building your application

From a high-level view, you will build the app following these steps.

  1. Build the admin application. This is the first step because your database is created in this step. This does not require any programming because the Wizard will generate it for you, besides creating the APIs needed for the app registration and sign-in functions in your app. Refer to the Wizard User Guide for details.
If you do not need or want the admin application now (you can always add it later), you will start with the minimal Admin project, which is available in the WebIDE itself. Open the "Mobile app Quick Start" from the "Help" menu. You will find a link to download the Minimal admin app, and instructions on how to deploy it. You can later enhance it for other admin functions.
  1. Write the business APIs. The data that your app uses will be stored on the server and the app will use the APIs to access it. Refer to the WebIDE User Guide for details. This is not mandatory, the data for your app can also be served from canned JSON files stored with the app itself.
  2. Build your app. This is the focus of this guide - the front-end apps.

Steps 2 and 3 above are not strictly separate steps. You will work on these simultaneously and switch back and forth as necessary. Both are a part of the same project and built using the same WebIDE - working on these two steps together is quite natural.

You will build two different projects. The admin application is entirely generated. To maintain modularity, this will have only the admin app related customization, and we will not add any consumer apps to it. We will refer to this as the base (or foundation) project. As mentioned before, you can start with the provided Minimal project.

You will build a second project to contain the front-end and the supporting business APIs. Let us call this one the extension project.

Notice that the front-end apps and the business APIs are in the same project allowing you to build the two as a single activity. If you prefer, you can keep the front-end and the APIs as separate projects - there can be multiple extension projects allowing you to spread the functionality any logical manner you find fit.
  1. Create a folder on your desktop to hold all project files. The admin app requires a configuration JSON and supporting customization files. Save local copies in this folder.
  2. Your working project is directly deployed on the server, without need for a local save - but it is recommended to locally save the project periodically. Use the same project folder to save this.
  3. It is good practice to name the second project by adding "-X" suffix (for extension) to the name of the base project.
  4. For ease of database management, define all your tables in the base app configuration - even the ones that do not require admin functionality (entities with type "transaction" are not managed by the admin app).

The WEB-APPLICATION Node

The front-end applications are added to the extension project. Multiple front-end applications can be created in the same project; and, multiple extension projects can be created for each front-end application.

A related node in your schema - APP-COMMONS - contains those parts of your application which are reused across applications. Examples are styles, components and assets.

Start by adding the WEB-APPLICATION node to your schema. Even though the name suggests it is for web apps, it is used for both web and mobile apps. If your web and mobile apps have similar structure, you can first define a structure and then clone it - this will save you the effort of defining the structure again. Once the basic structure is in place, you can develop the two independently. The structure, for our purpose, consists of-

  1. The pages (APP-PAGE node) and their layout.
    • The layout is specified as a top-down breakdown of the viewable space. The broken-down components in the layout are called views (APP-VIEW node).
    • The lowest level element in the layout that holds an elementary piece of information is called an Element (APP-ELEMENT node).
  2. The high-level navigation - the one controlled by actions on the navigation bars.
  3. The data binding for each view and element.
    • The data binding also follows a hierarchical breakdown closely mapped with the data structure that feeds data to the view.
    • Each view can have its own data source (API) or it can inherit data from its parent view.

Spend some time closely examining the WEB-APPLICATION properties screenshot below. You will define the application-level behavior and controls here. This also gives you an idea of the amount of work automatically handles for you.

WEB-APPLICATION properties .

Notes:

  1. Your app will have a URL even though it may be a mobile app.
    • This URL serves as the gateway to serve other APIs used in the application or data management.
    • Having a single URL for the entire application helps in hosting the application behind a firewall and the external URL (for web-apps) can be a different convenient name.
  2. You can configure the details of the sign-in module - this is managed by the system. The associated foundation project contains the server-side database and APIs to support this functionality.
  3. The web application can be optionally rendered as PWA, which can also be configured.

Image, Data and HTML assets

Add the image assets in your application using APP-ASSETS under APP-COMMONS, and then APP-IMAGE nodes under that. Make sure the images have appropriate size and resolution for the purpose you intend to use them for. Note that the mobile app (flutter) IDE requires certain app icon images to be provided separately for Android and iOS - these are not a part of the image assets here.

Your project may also require static data files - these should be added as APP-DATA nodes under APP-ASSETS. Only JSON formatted data files are supported, make sure the data is valid JSON - use a validation tool if required.

Your front-end apps can use locally served HTML content (rendered as WebView in Mobile app). Create your HTML content under APP-ASSETS as APP-CONTENT node. The APP-CONTENT can be hierarchical allowing entire web applications to served locally from the app. The WebIDE also allows you a short-cut to import the web app from a ZIP file.

Pages and Layout

You add APP-PAGE nodes under the WEB-APPLICATION, for each page in your app. Leave the sign-in and sign-up pages out because the system manages it for you. Include all functional pages, whether launched from the menu nav bars or invoked from app interaction.

Create the layout of each by hierarchically adding APP-VIEW and APP-ELEMENT nodes inside the page. The intermediate views in the page will segment the area into rows, columns or grids and the lowest level views will consist of elements - where you will display the data and accept user inputs. provides a wide selection of element types for different needs.

ZOAPIIO WebIDE has a layout visualizer and editor but is rudimentary in functionality. It allows you to break down the page hierarchically and view the layout but does not offer detailed controls like a professional design tool you might have seen. It is recommended that you have the layout that you want drawn on a piece of paper when you start.

As you define the page layout, build and then run it on the phone emulator, you may encounter errors from the Flutter layout engine. We have some tips-

  1. Start with a layout that only focusses on dividing the page into views and content for each view. Do not worry about sizing, alignments and scrolling.
  2. Gradually use view options like 'padding', 'detailed style', 'scroll', 'expand', 'center' etc. to improve the presentation.
  3. On a page, use the Scroll option in only one view. The easiest is to use it on the top view only. If you decide to use scroll on an inside view, do not set scrolling for the top view.
  4. For complex scrolling control, get the page to work correctly first, then you can try adding 'scroll' to multiple views. Revert if something breaks.
  5. Use of 'expand' option is most likely to throw your layout into errors because there are restrictions on its use by Flutter. When you first build your layout, do not use 'expand' at all.
  6. Gradually, add 'expand' option to views and revert if something breaks.
  7. Sometimes, a few trial-and-error cycles are needed in getting the layout right.
  8. In extreme cases, if you cannot get a layout of your desire, you can resort to native Flutter implementation of the view.

Floating Action Button

The mobile app pages can optionally have a Floating Action button - a button displayed as an overlay on the page. Sometimes, you want to provide quick access to certain function without making the user go to the Navigation Menu. The Floating Action button not only draws user's attention to the existence of the feature but also makes is directly accessible.

Flutter has a large collection of Floating Action controls; some even allow you to create a sub-menu around the button. implementation renders a simple circular button that fires the 'floatingaction' event. You can provide an alternate implementation of the button by overriding the following function in the PAGE-FLUTTER code.

Widget? getFloatingActionButton(String? fabicon, String? fabcolor, String? fabsize)
	

Your custom implementation can fire other events which you can then handle in your code. The example below uses the Flutter Widget FabCircularMenu to implement a sub-menu around the Floating Action Button.

@override
Widget? getFloatingActionButton(String? fabicon, String? fabcolor, String? fabsize) {
  return FabCircularMenu(
    children: [
      IconButton(icon: Icon(MdiIcons.fromString('keyboard'), size: 32), onPressed: () {
        $.app.fire('floatingaction-1', pagename, '', null);
      }),
      IconButton(icon: Icon(MdiIcons.fromString('contacts-outline'), size: 32), onPressed: () {
        $.app.fire('floatingaction-2', pagename, '', null);
      })
    ],
    fabSize: 48,
    ringColor: Colors.white.withOpacity(0.5),
    ringWidth: 80,
    ringDiameter: 200,
    fabColor: $.app.toColor('#e8dcd4'),
    fabOpenIcon: (fabicon == null)
        ? Icon(Icons.menu)
        : Icon(MdiIcons.fromString(fabicon))
    );
}

Data binding

Your application pages will include data that is supplied from outside - from the server API, for instance. You incorporate this in your pages using Data binding. Server APIs are not the only source of data for your application, it can be canned data provided as a data asset file (JSON) - see APP-DATA, or the app context (in-memory app data).

The page rendering is fundamentally different for HTML (Web) apps and Flutter (Mobile) apps. tries to create a common model for both, but you should be aware of differences because the underlying implementations are very different. In HTML, an element on the page can be directly referenced and changed and the program has full flexibility in doing so.

Flutter, however, only allows views (Widgets) to be updated from their state data. Data binding is used to implement this behavior. For your mobile app, any view that you want to dynamically change at run-time (user interactivity), must be bound to a data element (it can be structure). If the data to be bound does not originate from a server API, it can be bound to a local data source.

Data Source, Root and Binding

Routing data to your app pages is controlled through these properties. Data source and root properties are applicable only for a view and binding applies to both views and elements. The rules are as follows:

  1. All data sources (API, canned, or app context) used in your app must declare their structure in the project schema.
  2. When defining the data source for a view, you must identify the node in the schema that contains the definition of the source structure. This is essential, otherwise cannot manage the data inside the page.
  3. A view can have its own data source, or it can be bound to a sub-structure from its parent.
  4. Multiple data sources can be a part of the same page.
  5. Data source or binding is not mandatory for a view. For instance, a view may not require any external data.
  6. If a view does not explicitly bind itself to a source or parent's data sub-structure, it inherits the same binding as its parent.
  7. If bound, a view must be bound to an object in the source - it cannot be an elementary data item.
  8. Elements can have bindings for their value, label, help and herotag properties. Each can be a fixed literal value or a binding to an elementary item in its parent view's binding.

As noted - the app context is a simple hash, mapping names to values (possibly objects). Data source property can reference data from the app context. Please note that you must programmatically populate the app context with correct values before pages containing the referenced data are called.

Data source can take one of the following forms-

  1. A name in format appcontext:name. The name is looked up in the app context and that value (which should an object) is used as source.
  2. A name starting with http:, or https:. It is taken to an external API which is called to fetch the source.
  3. A name starting with /. It is taken to a service API and is called to fetch the source.
  4. Any other name. It is taken to be the name of a data asset (See APP-DATA) in the project, the contents of which are used as the source.

Additionally, with an API URL, app context substitutions can be used to include parameters to the API using the {{}} notation. E.g. http://host.com/products/{{productid}}, where productid is picked up from the app context and substituted for {{productid}}, before calling the API.

Lists

Frequently, you will require to render lists. A list is a block of data that repeats and is rendered to the user as a view or element that repeats following a layout.

While creating the page/view layout you will specify the topology (layout) for it. For instance, a commonly used layout is the column - this means that all its children will be laid out vertically.

If you bind a view to a data object which is an array (declared with DUPLICATES true), then you must provide another topology (layout) for the array - the Container Layout. For instance, if you choose row as layout and column as the Container Layout, then the child elements of the view will appear in a row and the same row structure will be repeated for all data objects in the array, as a column.

Advanced List features

provides a host of value-added functionality when rendering lists. Typically displaying of lists is usually associated with a search functionality allowing the user to search the list. This feature is available as an advanced List control.

Another feature that is available as a part of advanced control is list editing. Typically, the editing of list is achieved by displaying the list and then taking the user on an edit page to edit individual entries. However, with you have the option of the list being directly editable on the same page - you may find this behavior more user-friendly for your users.

For a list that is mapped to a repeating data element (array), you can searchable, lateedit, and latedelete under Control Options. See APP-VIEW.

Styling the app

uses a function first development approach. This means that when developing the app, you will focus on getting the functionality and page content hierarchy right. Both Flutter and CSS/Bulma provide a comprehensive level of styling control to the developers. does not attempt to abstract every fine detail and nuance, because it would defeat the purpose of abstraction.

The style abstraction is, nevertheless, quite comprehensive and should meet most requirements-

  1. For elements, there are ten named styles - black, white, dark, light, primary, link, info, success, warning, and danger.
  2. When defining an element, you can select one of the above. Each of these styles come with basic default colors and fonts, which is used to render the element.
  3. Some basic styling properties can be overridden in the element definition itself.
  4. Same applies for the views.
  5. Under APP-COMMONS -> APP-STYLE, you add APPVIEW-STYLE and APPELEMENT-STYLE Tags, which allow a more detailed configuration of styling parameters for Views and Elements respectively.
  6. With each Element or View definition, you assign the corresponding Detailed Style, to apply that style to the element or view.
  7. You can also permanently map all the ten named styles to your custom detailed element styles. Then you do not have to assign your custom style to each element separately.
  8. At the next level of control, you can provide a custom Flutter implementation of certain methods that control the style. See APP-FLUTTER under reference Guide.
  9. And finally, this is always there.
Web Applications use CSS which you can directly modify. So, chances are you will never run of styling options for Web. For mobile, however, if you have a styling requirement that abstraction is not able to meet, you have the option of creating a custom component, where you provide the complete implementation in Flutter.

App navigation

In app, you can have a default navigation plan for the app and you can optionally override it for each page. The navigation plan consists of buttons that will appear on the navigation bars located at the top and/or bottom of the user screen.

You add "APP-NAVIGATION" tag to your application and on pages where you need a different navigation. Within that you add the list of commands and the location of the command button. The button can be positioned on the navigation bar itself (left or right) or on the dropdown menu that is launched from one of the navigation bars. There is a great deal of flexibility on how you decide to structure the navigation controls. A command can be placed on both the top and bottom bar, if required. The dropdown menus themselves are available on both nav bars.

You can attach one of the following actions with each command in the navigation -

  1. Transition to another named page.
  2. Launch the named page as a modal popup with a close button. This can be used to display alerts and information messages.
  3. Login/Logout function. The label for this button is automatically set based on the current logged in status of the user. The command then allows the user to login or logout.
  4. Programmed handling. In this case, the system does not take any action and you must handle the event programmatically. See events.

Data routing

manages data inputs from the user and automatically makes it available to the API services that are bound to the views. System also automatically renders the views from the API output based on the data bindings.

  1. All input fields on a page are captured as a flat set of "Name-Value" tuples.
  2. These values are passed as standard POST HTTP parameters to the API calls in the page that is invoked from the page.
  3. This works when the page invocation is automatic (in response to a Submit) or programmatic from custom code provided by you.

Server-driven UI

This is a relatively new trend in mobile app development to deal with the challenges associated with pushing your app to your existing users.

  1. With every push to the play store, there is a publishing process that can take a few days.
  2. Even after the app is in the play store, it can take many days - even weeks - before the app is updated for all users. You will have to deal with your users running different versions of your app.
  3. The problem gets further compounded with bugs in your app. If a buggy update gets into circulation, it could take many days before it can be flushed out via an update. This could even affect your business.

In Server-driven mobile UI, you push the description of the page composition via an API from the server, and the app uses that description to render itself.

Building Server-driven mobile UI is a breeze with . No extra steps are required, you simply flag parts of your application that you want server-driven and manages the rest. Pages, views, assets, and even navigation commands can be flagged for server rendering. There are some rules, though-

  1. You can flag an entire page as Server-driven. This allows you to add completely new pages to your app on-the-fly. There is a caveat here, though. The page cannot have any Flutter/dart code in it, for instance, to handle custom interactivity. The reason is obvious - the flutter code needs to be compiled into the app and cannot be pushed dynamically.
  2. If a page was static when it was pushed to the play store, you can still override it by changing to Server-driven.
  3. In pages that are not Server-driven, you can flag specific views to be Server-driven. The advantage of this is that you can have Flutter/dart code that is pushed along with the page to the app, but the content, layout, rendering can be altered on-the-fly.
  4. App Assets can also be flagged as Server-driven - such assets are not baked into the app, are fetched by the app dynamically.
  5. App Navigation commands can also be flagged as Server-driven. You can add additional commands to the navbars and override existing ones using this. Please note that adding a command of type "Programmed" requires a handler to be present in your app.

User interactivity

Besides the App navigation, the users will interact with the app by clicking/tapping on elements on the page. In HTML and JavaScript, event handlers can be attached to elements even after they are created. In Flutter, however, the event handler must be provided at the time of creating the element. provides a common model for Web and Mobile apps for letting users interact with your app. This is done through events. The $.app object, that we have seen before, manages these events.

Event routing

The 'fire' and 'listen' methods are used for this. When you define an element on the page (WebIDE), you also mention the events you are interested in, from that element. Then you can take action when these events occur.

  1. For elements of type 'button', the event 'pressed' is implied and is same for both web and mobile apps (for consistency) - you do not need to mention it in your list.
  2. For element of type 'submit', the event 'submit' is fired and handled within the system. The default submit behavior is to validate the form and if there are no validation errors, the control is passed to the next page along with all the form fields.
  3. If you want a different behavior - such as additional validations - use the type 'button' and listen to the 'pressed' event.

The data that is passed at the time of 'fire' is passed to handler mentioned in the 'listen'. Normally, you will not need to fire the events in your program because the system does it automatically based on the events that you have mentioned in the element definition. The event names are the ones that HTML uses - E.g., click, doubleclick, mousever etc. These names are also the same for both web and mobile for consistency - internal implementation will use the appropriate equivalent.

You may use the 'fire' function if you require custom events. There is no restriction on the names of the events, you can use your own custom event names and trigger/handle them programmatically.

Function Web App (JS/jQuery) Mobile App (Dart/Flutter)
The global UI object $.app $.app
Listen to an event $.app.listen(eventname, pagename, elementname, handler) $.app.listen(eventname, pagename, elementname, handler);
Trigger (fire) an event $.app.fire(eventname, pagename, elementname, handler, data) $.app.fire(eventname, pagename, elementname, handler, data);
Event processing in front-end.

Event handling

As already mentioned, you handle events though the listen function of the $.app object. An event is uniquely identified as the combination of event name, the page name, and the element name. It is important to note that only one listener can be attached to an event. If you attempt to attach another listener (I.e. call the listen on the same event), the previous one is removed.

So, where should be listening code be placed? For web apps, there is only one place, which is the PAGE-SCRIPT attached to the page. For web apps, although you can override the view layout with HTML code, no JavaScript can be placed there. You must put all listen commands in the PAGE-SCRIPT, there is one for every page.

For mobile apps, you can override the view layout using Flutter code. Besides overriding the _buildWidget method, you can also add initState method to the widget. You can add other widget lifecycle methods there too. The body of the initState method is the right place to listen to events and handle them.

Conditional Activation

has a unique feature for Mobile apps that can be very convenient in managing user interactivity. Some parts of the mobile app (Views, Elements, Navigation Command, and Floating Action button on pages) can be associated with activation codes. The activation codes are programmatically maintained, and the system will switch on/off rendering of the linked UI element.

Updating the user view

Updating the user view is simple and straight forward in HTML/JavaScript/jQuery. You can reference any element by its Id, Class or Name attribute and modify its content.

For Mobile apps, rebuild method of $.app object is used. You will recall from our earlier discussion that any view that you need to programmatically update must be bound to some data (server API or local data asset). This is because Flutter requires that data to be a part of the Widget state.

Dart is a strongly typed language, although you can use untyped variables and structures. The use of strong typing allows for error detection at the time of compilation and leaves you more confident that the code will not blow up at runtime - though the chances are that it still will, for other reasons. takes advantage of the strong typing feature and generates data classes for you based on the data schema you have provided. When a view is rendered, an object of the mapped data class is passed to it - it is not a generic Dart map, but object of a class.

If you are updating a view, you must update this object before the rebuild, otherwise the view will remain unchanged because the underlying data will remain same. The state data for the Widget corresponding to the view can be updated by providing an object of Dart Map<String,dynamic> type. This object should only contain the changes to the original object, which itself was created from the JSON data from its source.

The last parameter to the fire method is this object. The changes from this object are first applied to the state object and then the rebuild of the view is performed. You should examine the generated data classes to know what fields are present in the object.

An example of the rebuild usage is given below -

$.app.listen('click', 'CALCULATOR', 'CBUTTON', (var w) {
	print('CBUTTON Click');
	Text t=w as Text;
	Calculator calc=$.app.state['calc'] as Calculator;
	String val=t.data ?? '';
	var result=calc.key(val);
	$.app.fire('rebuild', 'CALCULATOR', 'CALCTOP', {'value': result});
});

Manipulating the page view

The views and elements on your app pages get their behavior and looks from the configuration you provide in the WebIDE. Certain default behavior is applied to the input elements.

  1. When user interacts with these elements, events are dispatched for you to action them in your program.
  2. When navigating between pages, the values entered by the user on a page is made available to the API services on the next page.

At times you may want to modify the configuration of the input element when handing user interactivity. E.g. you may want to disable input on a field based on some condition or may want to alter the look (display properties like style, size, label etc.) at run time. You may also want to change the data displayed on the page in response of some event.

You will use the rebuild method of the $.app object for this. See the $.app Object reference for details.

Mobile app examples-

// Disable input on Element
$.app.rebuild('page-name', 'element-name', {'inputdisabled': true});

// Set counter (property in the bound object) to 2.
$.app.rebuild('page-name', 'view-name', {'counter': 2});

// Increment counter by 1 - by passing patchdata as a function.
$.app.rebuild('page-name', 'view-name', (viewdata) { viewdata['counter']++; });

Web app example-

// Disable input on Element. element is the DOM node.
$.app.rebuild(element, {'inputdisabled': true});

$.app Object Reference

Web app (JS) WIP

$.app method Return Type Parameters Description
fire Fire an event




getAppContext




getData Fetch the data from an URL




listen Register a listener for an event




loadPage Transition to the named page




patchAppContext Update the app context




popupPage Open the named page as a popup (dialog)
$.app JS reference (INCOMPLETE)

Mobile app (Flutter)

$.app method Return Type Parameters Description
fire void String eventtype,
String pagename,
String target,
dynamic data
Fire an event. Event names are generic, and the apps can use any arbitrary name. System fires some fixed event (E.g. nav, pressed, click, rebuild). Apps can fire system events also. The target of the event is identified by the pagename and the target (View or Element). Finally, with the event arbitrary data can be passed which is delivered to the listen handler.




formdata String? String pagename,
String target,
String value

Set/Get the values in form data. Form data is data that will be sent to the server when the page is submitted.

When an input element on the page is changed, this value is updated immediately. If you are writing a custom component, you should make this call to update the form data when its value changes.

target is the name of the element and value is the new value. To query the value, pass null for the value.





currentContext BuildContext? None. This is the BuildContext for the currently displayed page made accessible to your programs. This is not a function but a variable, which can be directly accessed like $.app.currentContext.




getAppContext dynamic String name
Get an entry from the app context




assetUrl String String assetname
Returns the URL of an asset (APP-ASSET). In Flutter you must obtain the URL of the asset before you can access it.




getData Future String url,
Map<String,dynamic>? postdata,
Map<String,String>? headers,
Fetch the data from an URL. postdata and headers are optional and named parameters. The method returns a Future<dynamic> object. When the future completes, it resolves to the data received from the API.




getViewData dynamic String viewname,
String (Named Parameter) as,
Get the data using which a view was populated. This will be the content of the object that was bound to the view. as parameter can be object or json.




getFieldValue String? String pagename,
String target,
Get the current value, including the changes typed by the user, of an Element on the page. The target must be an Element name




getImage Image (Flutter object) String url,
double width (Named),
double height (Named),
BoxFit? fit (Named)

Create an Image object from a source. If the url starts with 'http', the image is retrieved from the URL; if it starts with 'data:', the image is created from the URL; otherwise it is assumed to be a local asset name and the image is created from the asset.

Other optional parameters, if provided, are applied on the image while creating it.





jsonParse Map<String,dynamic> String? json

This method converts a JSON string to Dart Map object.





listen void String type,
String pagename,
String target,
void Function(dynamic) handler

Register a listener for an event. You must specify the event name and identify the sending element/view through the pagename and target (which can be view name or element name). For 'nav' events, the pagename is always blank and the target name is the name of the nav command.

The handler receives as parameter an object whose type depends on the event being handled. If the event target is a view, the parameter is of type UIView and if the target is an element, the parameter is of type UIElement. (See Helper classes below).

A simplified call of this method is available at page level (inside PAGE-FLUTTER). You do not need to use the $.app. prefix and the pagename parameter is omitted (Current page is assumed). The call syntax is -

listen(String type, String target, void Function(dynamic) handler);




loadPage void UIPage? currentpage,
String pagename,
bool replace,
Map<String,dynamic>? patchcontext (Named),
Map<String,dynamic>? patchformdata (Named)

Transition to the named page. If 'replace' is true, the loaded page replaces the top of page stack (See Flutter documentation). Otherwise, it is added on top of the page stack.

This call requires a handle to current page from where you are making this call. This is available to your programs as 'widget.page'. 'pagename' is the name of the page to load.

Last two parameters are optional and named. They respectively contain any changes you want to make to the app context and the formdata being submitted, before loading the page.





callPage Future UIPage currentpage,
String pagename,
Map<String,dynamic>? patchcontext (Named),
Map<String,dynamic>? patchformdata (Named)

It is similar to loadPage, except that you can receive a return value from the page when the page closes.

The called page must return the value by calling the flutter pop() method on the Flutter Navigator. Example-

Navigator.of($.app.currentContext!).pop(Value_to_be_returned);




loggedIn bool

Returns whether the user is logged in or not. If the user is logged in the user details can be retrieved using the loginInfo method.





loginInfo dynamic

Returns information about the current logged in user. The returned value is a Map object.

If the login data is in the process of being fetched from the server, a null object will be returned. To do an explicit wait for the data to arrive, you can use-

await $.app.getUserInfo();




patchAppContext void Map<String,dynamic>? patchdata
Update the app context. App context is a global Hash map, preserved across pages. This allows you to pass information between pages. The data bound to app views can also reference elements from it. Updates are applied while retaining the unchanged entries.




setActivation void Map<String,bool>? activationset
Update the current activation settings. This call replacess existing activation Map with the new one. An activation code can be mapped to a true/false value indicating its activation status.




patchActivation void Map<String,bool>? patchset
Update the current activation settings. This call updates the existing activation Map without disturbing unaffected entries.




getActivation bool String? activationcode
Get the current activation setting for the activation code.




popupPage void UIPage? currentpage,
String pagename,
Map<String,dynamic>? patchcontext,
Map<String,dynamic>? patchformdata
Works like 'loadPage', except the page is opened as a popup.




rebuild void

Rebuild a view or an element with changes. The rebuild method works differently for views and elements, described separately below.





rebuild (View) void String pagename,
String viewname,
dynamic patchdata

For the view, the patchdata contains updates to the data object that is bound with the view. It can be a Function which receives the current bound object as parameter and it returns the updated object. Alternatively, it can be an object containing values to be updated. Only values present in the patchdata are updated, others remain unchanged.

Also for the view, the nested views are also automatically updated to reflect the data changes.





rebuild (Element) void String pagename,
String elementname,
dynamic patchdata

For the element, the patchdata contains updates to the element properties - it cannot be a Function. The properties that can be updated are the following and the new property values are in the same format that you provide in the WebIDE, when configuring the element. See Helper Class UIElement for the list of properties.

Example (Page Flutter code)-

void init() {
  // CBUTTON and CALCVAL are elements.
  $.app.state['calc'] = Calculator();
  $.app.listen('pressed', 'CALCULATOR', 'CBUTTON', (var w) {
    print('CBUTTON Click');
    UIElement t=w as UIElement;
    Calculator calc=$.app.state['calc'] as Calculator;
    String val=t.prop('label') ?? '';
    var result=calc.key(val);
    $.app.rebuild('CALCULATOR', 'CALCVAL', {'value': result});
  });
}




scroll void String pagename,
String target,
String to

Scrolls the page to the specified location. pagename should refer to the current page (this.pagename), target should be the view name which should be scrolled and to should be one of 'top' or 'bottom'.





showNotification void String type,
String title,
String message

Displays a notification to the user. type can be 'info', 'warning', or 'danger'.





toColor Color (Flutter Object) String colorname

Convers a named builtin style or a Hex value (if it starts with #) to a Color that can be used for a flutter parameter requiring color.

$.app Flutter reference

Helper Class UIView

UIView is the internal implementation of View. A reference of the object is passed to the handler listening to events on the View. The handler can query the properties of the view using the prop method.

Method Return Type Parameters Description
prop dynamic String name

Query a property of the view. The following is the list of properties and their respective data types.

  1. events: String,
  2. layout: String,
  3. center: bool,
  4. scroll: bool,
  5. safearea: bool,
  6. expand: bool,
  7. reversetabs: bool,
  8. padding: String,
  9. label: String,
  10. displaystyle: String,
  11. displaysize: String,
  12. displayicon: String,
  13. width: int,
  14. widthispct: bool,
  15. data: UIData

Helper Class UIElement

UIElement is the internal implementation of the Element. A reference of the object is passed to the handler listening to events on the Element. The handler can query the properties of the view using the prop method.

Method Return Type Parameters Description
prop dynamic String name

Query a property of the view. The following is the list of properties and their respective data types.

  1. addonicon: String
  2. addonlabel: String
  3. addonside: String
  4. addonstyle: String
  5. addontype: String
  6. events: String
  7. displayalign: String
  8. displaysize: String
  9. displaystyle: String
  10. displaywidth: int
  11. displaywidthispct: bool
  12. help: String
  13. inputrequired: bool
  14. inputdisabled: bool
  15. label: String
  16. padding: String
  17. selectoptions: String
  18. validationregex: String
  19. value: String

Helper Class UIData

UIData is the internal implementation of Data structure associated with a View. A reference to the view data can be obtained by querying the data property.

Method Return Type Parameters Description
resolveValue dynamic String? name

Query a value from the data. If a name is provided the vaue of the named property in data is returned, and if the name is null, the entire data associated with the view is returned as a dynamic hash.


Push notifications

apps have pre-configured push messaging capability using Firebase Cloud Messaging (FCM) - the messaging platform from Google. You will need to -

  1. Create a project on Firebase,
  2. Add apps to the project (for each mobile app),
  3. Acquire the keys and configuration files, and
  4. Finally, add the keys/configuration to your ZOAPIIO project.
    • The Server key should be copied to your Web App properties in WebIDE.
    • The Configuration files should be added to your Mobile project - the configuration for Cordova and Flutter are different.

Please refer to the documentation on Firebase and Cordova/Flutter configuration for the same.

Once your app is compiled and ready, you can send push notifications to the logged in B2C users, from the Admin console of the Base (foundation) Project. To send push notifications from your application (Server APIs), compose a JSON object with following structure -

	{
		"to": "<the Id of the user from the b2cuser entity in your base project>",
		"notification": {
			"title": "The title of the notification message",
			"body": "The text of the notification message"
		}
	}
	

Then, serialize it into a string, and send to the provided MQ destination as text. The following Biz rule in your WebIDE will accomplish this-

	JmsSend to Destination FCMPUSH-QUEUE /Path/to/MessageNode@_JSON
	

Launching the Web App

The web app is served from the container. This is the most efficient way to render the web app because the instance also holds all your services and data.

It is easy to launch the web app. Simply right click on the WEB-APPLICATION node in your WebIDE and click on "Launch Application". You can also launch it by directly typing its URL in the browser. The app URL is constructed from your instance URL, the app URL and finally appending '/index' to it.

Native Mobile (Flutter) App

Running and testing your mobile app requires you to setup the Flutter development environment on your machine. Flutter is supported on multiple IDEs - most popular being the Android Studio, and Visual Code. You will need to acquire some basic Flutter knowledge - there are several Internet resources available that will get you started very quickly. Pick an IDE and that you are comfortable with and install the flutter environment. WebIDE will generate the Flutter source code, which you must copy into an empty Flutter project shell.

  1. Install the Flutter environment and create a new project.
  2. From the ZOAPIIO WebIDE, under the Tools menu, select the "Generate Flutter Project" command.
  3. Select the application (WEB-APPLICATION) that you want to generate and pick a server URL. When generating the Flutter app that will run with a different ZOAPIIO server, you should change the server URL - default value points to your development server.
  4. If all goes well, a ZIP file will be downloaded to your machine. Open it and you will find three folders - assets, images and lib. Copy these folders to your Flutter project folder (use the File Explorer to copy the files).
  5. Use your IDEs build, test, run and package commands to work with your mobile app.
  1. Use can use either a Mac or a Windows machine, but to be able to test the iOS build of your app, you are required to have a Mac for your development machine.
  2. Also, all mobile development environments (even before Flutter) are resource hungry. The same is true of Flutter - you need a development machine of a recent vintage.
  3. In the Flutter project, there is a special file called 'pubspec.yaml' which controls the project environment and external dependencies.
  4. Make sure the images and assets folders are exposed as project assets.
  5. assets:
    - images/
    - assets/
    		
  6. Also add the dependencies. The following is an example, your requirements may differ-
  7. dependencies:
    	cupertino_icons: ^1.0.3
    	event_bus: ^2.0.0
    	google_fonts: ^3.0.1
    
    dev_dependencies:
    	flutter_test:
    		sdk: flutter
    
    	http: ^0.13.3
    	flutter_spinkit: ^5.1.0
    	event_bus: ^2.0.0
    	device_info_plus: ^3.2.3
    	shared_preferences: any
    	animated_text_kit: ^4.2.1
    	geolocator: ^8.0.5
    	google_sign_in: ^5.3.2
    	flutter_facebook_auth: ^4.3.4
    	firebase_core: ^1.17.1
    	firebase_messaging: ^11.4.1
    	material_design_icons_flutter: ^5.0.6295
    	flutter_form_builder: 7.2.1
    	expressions: ^0.2.3
    	table_sticky_headers: ^2.0.0
    	flutter_inappwebview: ^5.4.3+7
    	flutter_titled_container: ^1.0.7
    	video_player: ^2.4.7
    	flick_video_player: ^0.5.0
    	visibility_detector: ^0.3.3
    	url_launcher: ^6.1.6
    		
  8. For Android build of the Flutter project, another file called 'AndriodManifest.xml' comes into the picture.
  9. Make sure the AndriodManifest.xml file grants access to the app to networking and other services by adding the following.
  10. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    	package="com.XXXX.YYY">
    	<uses-permission android:name="android.permission.INTERNET"/>
    	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    
    	<application...
    		
  11. iOS build will have a similar environment specific control file.
The flutter dependencies given above may not be the latest dependencies because flutter is changing rapidly and dependencies break with new releases. You should consult the "Mobile Quick start Guide" under "Help" on your Web-IDE for latest information.

Cordova Mobile App

Cordova is an open-source cross-platform mobile app development platform. The biggest plus in its favor is that you can take an existing web application and compile it for mobile - both Android and iOS. Only requirement is that your web app must be responsive, so that it renders well on the mobile screen.

Cordova mobile apps are not native apps, however. makes building Flutter apps very easy, but it is still not as direct as using Cordova. Depending upon the complexity of user interaction in your app, your target user profile and your development budget, you can decide your entry to the mobile app market. If you are not sure, we suggest you start with the Cordova app because it is faster to build and progressively advance to the native flutter app. Both are cross-platform.

Running and testing your Cordova mobile app requires you to set up the Cordova development environment on your machine. No IDE is required - it is mostly command line, but you can use an IDE, if you already have one. WebIDE will download the web app source code (HTML/CSS/JS) as bundle, which you must copy into an empty Cordova project shell.

  1. Install the Cordova environment and create a new project.
  2. From the ZOAPIIO WebIDE, under the Tools menu, select the "Generate Cordova Project" command.
  3. Select the application (WEB-APPLICATION) that you want to generate and pick a server URL. When generating the Flutter app that will run with a different ZOAPIIO server, you should change the server URL - default value points to your development server.
  4. If all goes well, a ZIP file will be downloaded to your machine. Open it and you will find the www folder. Copy the contents of this folder to the www folder of your Cordova app.
  5. That is all you need, just build your Cordova project and run.
  6. If you need to change the URL of the server for the app, you will find this in the index.html file, simply change the URL and rebuild. You can have different build for testing and production.

Reference Guide

Summary

Legend: Web App Only w. Mobile app only m.

Tag Description
WEB-APPLICATION The complete abstraction of your Web or Mobile app.
APP-CUSTOM m Place to put your non-UI related Dart classes - business functions or computational logic.
APP-FLUTTER m Place to put overrides for mobile app default styling.
APP-SPLASHPAGE m A page to display welcome animation or graphics before the first page.
APP-NAVIGATION App level navigation plan.
APP-NAVCOMMAND A specific command in the navigation plan
APP-PAGE Pages in your app.
APP-VIEW The content of the page is organized into views.
APP-VIEW Views can be nested.
APP-ELEMENT Leaf level content element that renders a piece of information or input control.
APPVIEW-FLUTTER m Provide custom rendering for mobile app.
APPVIEW-HTML w Provide custom rendering for web app.
APPVIEW-WEBVIEW Indicates that the view is an embedded web app. If present, other tags are ignored.
PAGE-FLUTTER m Page level code to handle interactivity and override of styling.
PAGE-SCRIPT w Page level code to handle interactivity.
APP-NAVIGATION Navigation plan specific to the page.
APP-NAVCOMMAND Individual navigation command in the plan.


APP-COMMONS The parts of your app, which are shared across multiple apps - both web and mobile.
APP-META w Put all your meta tags here that you want in the web app home page.
APP-STYLE Put all your css code here to style the web app.
APPVIEW-STYLE Detailed style for a view.
APPELEMENT-STYLE Detailed style for an element.
APP-COMPONENT Define a custom component (Element) to augment the standard element set.
APPC-FLUTTER m Flutter implementation of the custom component.
APPC-JAVASCRIPT w Web implementation of the custom component.
APP-ASSETS Assets for your web or mobile app.
APP-DATA Canned JSON data.
APP-ASSET A non-image asset in the application.
APP-IMAGE Image
APP-CONTENT Local Web content (HTML/JS/CSS) that you want to embed in your app.
APP-CONTENT App content can be nested.
Organization of Web app Tags.

WEB-APPLICATION

"WEB-APPLICATION" is where you will define your application - web as well as mobile. In a project, you can have multiple applications.

Attribute Description
URL Path The application must have a URL, even if it is a mobile application. The URL must start with '/wa', so the system knows it represents an application. System uses a prefix convention. You will recall that HTTP services need to start with '/wc/' etc.


Target Many Tags and properties in your WEB-APPLICATION hierarchy are applicable only to Web or Mobile apps. If your app is targeting only the web or the mobile, you can say so here. This will keep the inapplicable Tags and properties hidden and simplify your interface. Options are - web, mobile, and web&mobile.


Mnemonic Name This is for internal use. Give a short name without any special characters in it.


Market Name This is the brand name of your application. Give a short name, that your application will be known as to its customers.


Opening Page This is the page which will be displayed when the application opens. Select a name from one of the pages you will add to your application. If a splash page has been defined (mobile app only), it will be shown after the splash page. You will need to come back and update this property after you have added pages to your app.


Use Styles Your project can have multiple APP-STYLE definitions (Under APP-COMMONS). Select one of the APP-STYLE definitions to attach to the app.


Description Textual description for the purpose of documentation.


Login Type ZOAPIIO has login services for b2b and b2c type users. B2B users are added by the administrator, while the B2C users can subscribe themselves. Presently, this should be set to 'b2c' - b2b sign-up from apps is not supported.


Session Scope The system uses JWT for transmitting authenticated user information. You may build multiple apps running on the same ZOAPIIO container. So that their authentication scope is independent from one another, provide a unique value here.


Login Text The text you want to use for the login - E.g. 'Sign-In', or 'Login', etc.


Logout Text The text you want to use for the logout - E.g. 'Sign-Out', or 'Logout', etc.


Register Text The text you want to use for registration - E.g. 'Sign-Up', or 'Register', etc.


Foundation Project

The WebIDE is an integrated development environment for front-end and backend. The service APIs for login administration are a part of the Admin app - automatically generated by the Wizard. If your application has no admin functionality, use the built-in Minimal base project. From your WebIDE, follow instructions to Mobile app Quick Start,

Provide the name of foundation (or base or admin) project here.



Require Username Should the user be asked to pick a username at the time of registration.


Require Email Should the user be asked to provide her Email Id at the time of registration. Possible values are - 'yes', 'no', and 'with verification' (this will require the user to verify the email before registration).


Require Phone Should the user be asked to provide her Phone No at the time of registration. Possible values are - 'yes', 'no', and 'with verification' (this will require the user to verify the phone number through an OTP before registration).


Text/Email Sender Service

When selecting 'with verification', you must write a service to handle the actual delivery of the OTP to the user via email and/or phone. You should then, provide the URL of the service here.

The service will accept two inputs - the token and the destination phone/email. The service can determine the destination from the content (@ in the text implying email). The URL that you provide should have 2 placeholders for each value - #D (destination), and #T (token). The service should create the message text and then send it to the phone or email as applicable. The registration module will substitute the values and call this URL.



Additional Registration Fields If you want any additional fields at the time of registration, provide a comma separated list here. Only Age and Gender are supported at this time. These fields should also be declared in b2cuser table of the base app.


Login Page Style You can override the styling of the Login page by assigning one from your custom style (Under APP-STYLE).


Google Maps API Key If you are planning to use Google Maps in your application. Google Map support is planned in future.


Facebook App Code If you are planning to allow Facebook login to the users, provide the facebook app code here. This is also a planned feature.


Enable PWA Select it you want to allow your web application to be run as PWA.


PWA Properties (multiple) Enter PWA related properties here.


VAPID Keys When using notifications to the PWA in chrome-based systems, a VAPID key is required. You do not need to enter it; the designer allows you to generate the keys on the fly.
Attributes of the "WEB-APPLICATION" Tag.

APP-ASSETS

"APP-ASSETS" is used to input your application assets - Images and Data files. Create your assets under this tag. There are no attributes for this tag. For web applications, the assets are bound to the URL asset/{asset-name}. For mobile apps, the assets are reproduced in the generated folder under subfolders "assets", and "images" respectively. The data assets can be used as data source when binding to the app views.


APP-ASSET

"APP-ASSET" represents a non-image asset in your application.

Attribute Description
Name The name of the asset. It is referenced in the application by name. For web application the asset is bound to the url "asset/{name}". For Mobile app, the path of the asset can be obtained using a call to assetUrl on the $.app global object.


Server Driven You can designate any asset to be Server-driven. For details, see Server-driven UI.


Asset Any binary file can be an asset, upload from your local disk.


Description Textual description for documentation purposes.
Attributes of the "APP-ASSET" Tag.

APP-COMMONS

"APP-COMMONS" is used to aggregate together all parts of your app, which can be shared across multiple apps and between web and mobile apps.

APP-CUSTOM

"APP-CUSTOM" is applicable for mobile applications only. You can include any custom classes that your application requires, here. The code here is replicated in the generated Flutter project as 'custom.dart' and is automatically imported in all other generated dart files.

A sample script is given below. This implements a simple calculator class. For instance, if your application was implementing a calculator, you can add the computation logic here and keep your UI code clean and structured.

import 'package:expressions/expressions.dart';

class Calculator {
	String val = '0';

	String key(String keytext) {
		if (keytext == 'C') return (val = '0');
		if (keytext == '=' || keytext == '+-') {
			try {
				Expression expr = Expression.parse(val);
				const evaluator = ExpressionEvaluator();
				var result = evaluator.eval(expr, {});
				if (keytext == '+-') result *= 1;
				val = result.toString();
			} catch (err) {
				return val;
			}
		} else if (keytext == '()') {
			if (val == '0' || val == '') return (val = '(');
			var last = val.substring(val.length - 1);
			if (last.compareTo('0') >= 0 && last.compareTo('9') <= 0) {
				val += ')';
			} else if (last != '(') {
				val += '(';
			}
		} else {
			val += keytext;
		}
		return val;
	}
}

Attribute Description
Name The name of the script. Even though there is only one custom tag in your entire application, you should give a valid name.


Type This must be set to Dart because the mobile app uses Dart.


Description Textual description for the purpose of documentation.
Attributes of the "APP-CUSTOM" Tag.

APP-COMPONENT

Attribute Description
Name The name of the component. You will add it to your app pages as Element with type custom:COMPONENT-NAME. Provide the Web and/or Mobile implementation of the component by adding APPC-JAVASCRIPT and APPC-FLUTTER Tags under it.
Attributes of the "APP-COMPONENT" Tag.

APP-CONTENT

APP-CONTENT is used to define lightweight HTML content in the app itself. APPVIEW-WEBVIEW Tag in the app structure is used to embed it into the app pages. For Mobile, this is packed into the app itself - so do not define heavy content here.

APP-CONTENT Tag can be nested, allowing complete directory structure of your web application to be captured. Typically, even the simplest web content has separate CSS and JS folders, but there can be more. WebIDE also has a short-cut tool to import the APP-CONTENT from a ZIP file.

Attribute Description
Name The name of the asset - this can be any name not necessarily the name of the file.


Server Driven You can designate any asset to be Server-driven. For details, see Server-driven UI.


Content Type This value must be content type (MIME type) or folder if this is a folder in the app content structure.


Base64 Encoded Any binary content in your app must be Base64 Encoded and then this flag checked, so that system knows to decode it before use. Typically, you will use this for images, which are binary files. When using the ZIP import utility, the Base64 codification is automatically handled.


Relative Path

This must be the actual name of the folder or the file on disk. Your HTML content will have embedded reference to other files - so that these runtime references remain valid.

Please note that additional setting changes are required to the pubspec.yaml file in Flutter. Every asset folder needs explicit declaration.



Description Textual description for documentation purposes.
Attributes of the "APP-CONTENT" Tag.

APP-DATA

"APP-DATA" tag is used to embed fixed static data in your application. It can be associated as data source with a view in your application (data source is normally a service API URL).

Right-click on the tag to launch the editor, where you can type of paste your JSON text. Example-

{
	"Name": "World",
	"Count": 1
}

Attribute Description
Name The name of the DATA asset


Server Driven You can designate any asset to be Server-driven. For details, see Server-driven UI.


Type This value must be set to Json, because that is the only format being supported currently.


Description Textual description for documentation purposes.
Attributes of the "APP-DATA" Tag.

APP-ELEMENT

"APP-ELEMENT"s represent the data display/input elements on the page (both web and mobile).

Attribute Description
Name The name of the element - it is required because your programs will use the name to reference the element.


Description Textual description for documentation purposes.


Type The element type, valid values are-
  1. label - Display some text.
  2. text - This is same as label but allows you to style each differently by overriding in your code.
  3. input - A simple user input field.
  4. textarea - a longer multi-line text input field.
  5. password - like input, but the typed text is not displayed.
  6. username - like input, with decoration/validation rules for a username.
  7. email - like input, with decoration/validation of an email.
  8. tel - like input, with decoration/validation of a telephone number.
  9. number - numeric input field.
  10. date - date input field.
  11. select - a dropdown input field. (See Options attribute below).
  12. button - an action button, to be handled programmatically.
  13. submit - an action button to automatically submit the current page.
  14. checkbox - a checkbox input field.
  15. radio - a radio input field.
  16. image - displays an image.
  17. video - plays a video.
  18. hidden - a hidden input field.
  19. custom:COMPONENT-NAME - A custom component (should be declared in your app).


Options (If select) If the element type is 'select' or 'radio', provide the options separated by commas here.


Value (Binding) A fixed string or data element to be bound to this element - select from the options provided.


Events Certain events are emitted by default, others must be explicitly requested by naming them here. 'button' elements emit 'pressed' event and other input elements emit 'change' event by default. If you want other events, mention comma separated list here. Possible values - click, doubleclick, mouseover.


Style This value is based on Bulma styling options. Select one from the list. An approximate equivalent style is provided for mobile elements.


Size This is also based on Bulma values, and an approximate equivalent is chosen for mobile elements.


Text Align The alignment for the field - select from the list.


Icon (Material Design) Enter the name of an icon from Material Design library to be used with the element.


Label (Binding) The text to display for label, button and submit element types. Binding can be used in place of fixed text.


Help Message (Binding) For input elements, you can specify a short help text here. Binding can be used in place of fixed text.


Field Add On Both Bulma and Flutter allow you to create a combination input element where a button can be attached to the input field. You can apply an add on to the element, choose the position here - before or after.


Add On Type Add-on type can be button, submit or static. If button is specified, clicking/tapping the button will fire the 'addon' event from the element. If submit is specified, submit action is automatically performed.


Add On Label (Binding) Label for the add-on, can be a binding.


Add On Style Style for the add-on - select from list.


Add On Icon (Material Design) Enter the name of an icon from Material Design library if the add-on should be displayed with an icon. Both Web and Flutter apps use the Material Design icons set.


Detailed Style Optional, assign a detailed style definition from the app's style setting.


Input Required This is for validation of input fields - should an input be mandated on this field.


Input Disabled Should the input on the field be disabled?


Validation (regex) Provide a regular expression if the input value needs additional validation.


Activation Code Activation code for the element. See Conditional Activation.


Control Options Some finer element options, which are not abstracted as independent properties can be specified here in name=value,... format.
  1. max (integer) - applicable to numeric element, specifies max value that can be input.
  2. width (integer) - applicable to image type element, specifies the width of the image.
  3. height (integer) - applicable to image type element, specifies the height of the image.
  4. fit (One of - none, fill, cover, fitHeight, fitWidth, scaleDown, contain) - applicable to image type element, specifies how the image should be fit in the available area. Default is 'contain'.
  5. formatted (true/false) - applicable to text type element, specifies if the text being displayed should be formatted as per the current search phrase. The view in which this element appears should be 'searchable' (See Advanced list controls).
  6. Any custom value (Application specific) - applicable to custom elements, you can define and pass any control option and its value from here. The control can access it inside the program.


Html Id The Html Id - it will be reproduced as the id property of the generated HTML tag. This property has no effect for mobile app elements.


Html Class The Html Class - it is reproduced as the class property of the generated Html tag. You can provide multiple class names (space separated). The class name list can include Bulma class names or your custom class names (add corresponding style for the class under APP-STYLE tag. This property has no effect for mobile app elements.
Attributes of the "APP-ELEMENT" Tag.

APP-FLUTTER

APP-FLUTTER Tag is one for the app and you should add application-level event handling here. It also allows you to make application wide styling overrides. Most styling overrides can be handled at Element/View properties level, this is for advanced use only.

// Supply your implementation of following functions for a stylename and optionally elementtype.

// static initApp declaration is mandatory. You 
static void initApp() {
	// Application level Event handling goes here.
}

// Foreground color
Color foreground(String stylename, {String? elementtype})

// Background color
Color background(String stylename, {String? elementtype})

// Font size
double fontsize(String sizename, {String? elementtype})

// Letter Spacing
double? letterspacing(String sizename, {String? elementtype})

// Icon Size
double iconsize(String sizename, {String? elementtype})

// Text Style
TextStyle? textstyle(String stylename, String sizename, {String? elementtype, String? detailedstyle})

// Label Style
TextStyle? labelstyle(String stylename, String sizename, {String? detailedstyle})

// Helper Text Style
TextStyle? helperstyle(String stylename, String sizename, {String? detailedstyle})

// Button Style
ButtonStyle? buttonstyle(String stylename, String sizename, {String? elementtype})

// Apply a title to a view.
Widget applyViewTitle(Widget w, String title)

// Prepare the Menu Widget
Widget getMenuWidget(String iconname, String label, bool activationcheck)

// Get Decoration for the Tab bar
Decoration? getTabBarIndicator({bool reverse=false})

// Get Decoration of the input field.
InputDecoration getTextFieldDecoration(String type, String label, String help, String error,
	bool hasbutton, Widget? prefix, Widget? suffix)

// Create the Floating Action button
Widget? getFloatingActionButton(String? fabicon, String? fabcolor, String? fabsize)

Attribute Description
Type This must be set to Dart.


Description Textual description for documentation purposes.
Attributes of the "APP-FLUTTER" Tag.

APP-IMAGE

"APP-IMAGE" represents an image asset.

Attribute Description
Name The name of the image. It is referenced in the application by name. For web applications the image is bound to the URL "asset/{name}".


Server Driven You can designate any asset to be Server-driven. For details, see Server-driven UI.


Image The image itself, upload from your local disk.


Description Textual description for documentation purposes.
Attributes of the "APP-IMAGE" Tag.

APP-META

"APP-META" tag is relevant for web applications only. You can place HTML meta tags here - these are reproduced in the application home page. You can have multiple APPP-META tags, for each app you must name the one you want to use. Example-

<title>Sample App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
		

Attribute Description
Name A name. This is required and your app must reference the APP-META to be used using this name.


Type This must be set to Html because the contents are HTML


Description Textual description of the purpose of documentation.
Attributes of the "APP-META" Tag.

APP-NAVCOMMAND

"APP-NAVCOMMAND" represents a command button to be placed on one of the navigation bars in the app.

Attribute Description
Name The name of the command, it is a required attribute.


Server Driven You can designate a nav command to be Server-driven. For details, see Server-driven UI.


Html Id The Html Id - it will be reproduced as the id property of the generated HTML tag. This property has no effect for mobile app elements.


Html Class The Html Class - it is reproduced as the class property of the generated Html tag. You can provide multiple class names (space separated). The class name list can include Bulma class names or your custom class names (add corresponding style for the class under APP-STYLE tag. This property has no effect for mobile app elements.


On Top Navbar Where should it appear on the top bar - none, left, right or menu.


On Bottom Navbar Where should it appear on the bottom bar - none, left, right or menu.


Label The label for the command button.


Icon (Material Design) Enter the name of an icon from Material Design library if the button should be displayed with an icon. Both Web and Flutter apps use the Material Design icons set.


Action Type of action to be performed when the command is invoked - possible values are Load Page, Popup Page, Login/Logout, or Programmed. When Programmed is selected, system does not take any action. In the page script of your opening (home) page, you should listen to the "nav" event with blank pagename and target Command-Name, and handle it programmatically.


Action Target If the Action is set to "Load Page" or "Popup Page", you should specify the name of the page here.


Activation Code Activation code for the Command. See Conditional Activation.


Description Textual description for the purpose documentation.
Attributes of the "APP-NAVCOMMAND" Tag.

APP-NAVIGATION

"APP-NAVIGATION" is used to define the application navigation. Both web and mobile apps can have up to two navbars (top and bottom) - both are optional. APP-NAVIGATION is defined at the application level, but it can be overridden for specific pages. When overriding, the entire Navigation must be defined again. It is not possible to override certain parts of the default navigation.

Usually, the top navigation bar also has a logo. For web applications, the navigation bars can be fixed or floating - floating bars scroll with the page and do not remain fixed on the screen. For mobile applications, if you choose to have a navbar, it must be fixed.

Attribute Description
Name The name for convenience. The name itself has no significance.


Logo The Logo to be used in the top navbar, if present. The logo itself must be added as an image asset, and then named here.


Logo Height The height for the Logo


Top Navbar The nature of the top navbar - possible values are none, floating, or fixed.


Detailed Style Select detailed styling for the top navbar.


Popup Background Color Color for the Menu Popup.


Bottom Navbar The nature of bottom navbar - possible values are none, floating, or fixed.


Detailed Style Select detailed styling for the bottom navbar.


Description Textual description of the purpose of documentation.
Attributes of the "APP-NAVIGATION" Tag.

APP-PAGE

"APP-PAGE" represents a page in the application - both web and mobile. Add each page in your application here and configure the layout of each. The sign-up and registration are automatically managed by the system, and you should not define pages related to sign-in and sign-up.

With each page, you can say if a login is required to access the page. If you set this property to true for the homepage, then your application will force a login/sign-up before entry. Generally, you want to have a generic welcome page for all users and force login for functional pages.

Attribute Description
Name The name of the page. The pages are referenced by name.


Server Driven

You can designate a page as Server-driven by flick of a switch - rest of the page definition remains same. Once so marked, the app need not be generated/compiled and pushed to the app store. Once deployed, the changes take effect immediately.

A page marked as Server-driven cannot have any flutter/dart code in it for handling interactivity. The page works with default behavior in terms of navigation and flow. ZOAPIIO offers considerable flexibility for handling such situations - see Server-driven UI.



Label The page will usually have a human readable label, which is displayed with the page.



Navigation Select a Navigation to apply to the page.


Background Color This is specified in HTML (#RRGGBBOO) notation (OO is Opacity) and a helper control is available to select the color. After selecting the color you can manually type the Opacity value (in hex) at the end. The entire color value can also be typed.


Background Image Background image for the page.


Next Page 's navigation system automatically handles submit buttons on the page. All the input fields in the page are put in a name-value tuple connection and then the control is passed to the page that is named here. If this if left blank, the control is sent to itself (current page). You can, of course, not have any submit buttons on the page and handle button clicks programmatically.


Require Login Check this box, if the use cannot access the page, until she has registered and logged in.


Has Floating Action Check this box, if the page should have a Floating Action button. Details of the button can be provided in following attributes. Your program should listen to the 'floatingaction' event and take action when the button is clicked. You can also provide a custom implementation of the floating action button.


Icon (Material Design) Specify an icon for the Floating action button. The Floating action button cannot have a label because it is small in size.


Icon Size Size of the icon in Floating Action button.


Button Color The color of the Floating Action button.


FAB Activation Code Activation code for the Floating Action button. See Conditional Activation.


Description Textual description of the purpose of documentation.
Attributes of the "APP-PAGE" Tag.

APP-SPLASHPAGE

"APP-SPLASHPAGE" is applicable only for mobile apps and it not the same as what flutter calls the splash page. Flutter allows you to provide a splash page, which is shown for the fraction of a second it takes to load the application. If you require that, handle it in flutter.

This splash page is more like a flash page which can be flashed to the user as an introduction or some animation to enhance the app looks. The duration of flash is selectable, and typically should not be more than 2 seconds.

If you choose to have this flash page, you must provide the implementation as the _buildWidget method as shown in the example below-

Widget _buildWidget($LoginData? d) {
	return Image.asset('images/SPLASH.gif');
}

Attribute Description
Name The name of the page, it should be present.


Show Logo A very basic flash page is generated by the system, which is just a placeholder, until your build your own. Check this if you want the logo to be a part of the placeholder flash page.


Duration (ms) For how long, the flash page should be displayed.


Fetch Location If you plan to use the geo-location of the user in the flash page, check this box - before rendering the page, geolocation will be retrieved and passed to the render routine. If the user has logged in in the past, her details are also retrieved and passed to the flash routine.


Description Textual description for the purpose of documentation.
Attributes of the "APP-SPLASHPAGE" Tag.

APP-STYLE

"APP-STYLE" is CSS code that you write to provide styling information for the web application. It if ignored for mobile apps. When defining views and elements, you can add class names to the HTML elements that get generated. You can apply styling to elements using the class names.

web apps use Bulma styling framework. For styling, try to use Bulma classed where possible and add your own, only when necessary.

Attribute Description
Name The name, it is required and is used to refer to the app level styling. You can define multiple App Styles along with details under it. The App Style should be attached to the Web Application. You can simply change the style for the application effectively restyling the entire app.


Server Driven This boolean setting is to support the Server Driven UI feature. If the Style is flagged as server driven, it is not baked into the app but is pushed on the fly. This allows changing the style without requiring a recompile and App store update.


Type This must be set to Css.


'primary' override The built-in style primary can be mapped to a APPELEMENT-STYLE (Detailed Style) to apply it across the application.


Other (multiple) override There are element level style overrides available for all ten built-in styles.


Description Textual description for the purpose of documentation.
Attributes of the "APP-STYLE" Tag.

APP-VIEW

"APP-VIEW" nodes are the building blocks of the page layout. You start breaking the page down from top into views. At the lowest level are APP-ELEMENT nodes.

Attribute Description
Name The name of the view - it is required because your programs will use the name to reference the view.


Server Driven

You can designate a specific view as Server-driven simply by flick of a switch. If a page or a view is flagged as Server-driven, all contents below this are also server driven.

For details, see Server-driven UI.



Description Textual description for the purpose of documentation.


Layout How the contents of the view should be arranged. Possible values are-
  1. block - No specific layout is applied. Content is rendered in sequence. Use this if you are implementing your own rendering of the view.
  2. tabs - The views appearing directly under this are rendered using a tabbing control. A tab bar is shown allowing the user to switch tabs. Only one view in the nesting hierarchy is displayed at a time. The Label attribute contains the tab label.
  3. grid - A contents (next level of views) are rendered as a grid. The number of columns in the grid is determined by the width setting.
  4. column - The contents are laid out as a column.
  5. row - The contents are laid out as a row.
  6. field-row - this is a special layout for web apps only to render input elements in a row. The content of this view should be input elements.
  7. header - unused.
  8. footer - unused.


Desired Width The desired width of the view. It can be expressed as a plain number, or a number followed by a %.


Container Layout This property comes into picture when rendering a list (the view is bound to an array item). This layout is applied to the outer container that will house the list items. Possible values-
  1. free - No specific layout is applied. Content is rendered in sequence.
  2. grid - A contents (list items) are rendered as a grid. The number of columns in the grid is determined by the width setting.
  3. column - The list items are laid out as a column.
  4. row - The list items are laid out as a row.
  5. table - The list items are laid out as a table.


Data Source

The data source for the view. It can be left blank if there is no external data in the view or the binding of parent view should be used. You can type either the name of a local data asset or the URL of a ZOAPIIO service.

You can also drag and drop the nodes from the application schema representing the ENTRY-POINT or APP-DATA.

Source for the view can also be pointed to an in-memory data structure saved in Application Context. The app context can be accessed from your program, and you can put the data programmatically before the view is called to render. Use appcontext:app-context-entry-name, to use this feature.



Data Source Root The structure of the data that will be received from the data source needs to be declared in your project schema. Provide the path of the node in your schema that contains the definition of the structure.


Data Caching In mobile apps, when the user navigates to a page a second time, the default behavior is to display the last displayed data and then refresh it in the background. The options are default and off. Set it to 'off' to disable the default caching behavior on the page.


Data Binding Type the path of the data element relative to the data source assignment to which this view is bound or has inherited from its parent.


Events You can trap and handle user events at view level. Mention comma separated list here. Possible values - click, doubleclick, mouseover.


Label The label for your view.


Icon (Material Design) Enter the name of an icon from Material Design library if the tab label should be displayed with an icon. Both Web and Flutter apps use the Material Design icons set.


Style Select from one of the named styles.


Padding Specify the padding to be applied to the view here. Enter 1, 2 or 4 numeric values separated by space. The values sets are - single uniform padding, vertical and horizontal symmetric padding, or individual settings for top, right, bottom and left.


Detailed Style Optional, assign a detailed style definition from the app's view styles.


Card Display the view as with border and shadow - giving it the look of a card.


Center Check this box if you want the content to be centred.


Scroll This is applicable only for the mobile app and check this box if you want the contents of the view to be scrollable.


Expand This is a numeric value usually associated with Views appearing under a parent view with 'row' layout. This specifies in what proportion should the view be expanded in relation to other views in the same row. For example, if you specify 1 for every view in the row, they will all be expanded in same proportion. If you change one of the views to 2, then that view will expand at twice the rate in relation to others.


Safe Area This flag can be checked for the root view of the page to keep its rendering limited to the safe area on the user screen. It corresponds to the Safe Area concept used by Flutter.


Activation Code Activation code for the Command. See Conditional Activation.


Control Options Some finer view options, which are not abstracted as independent properties can be specified here in name=value,... format.
  1. searchable (true/false) - The List control will be rendered with a search control and apply search filter to the list while searching.
  2. lateedit (one of - inplace, true) - The list items will be rendered with an edit button, allowing the user to expand the display into an editable box where edit can be performed.
  3. latedelete (true/false) - The list items will be rendered with a delete button allowing the deletion of the items from the list. Delete undo operation is also provided.
  4. reversetabs (true/false) - Applicable for 'tabs' View, setting this to true will display the Tab controls at the bottom.
  5. autorotate (Milliseconds) - Applicable for only Web app and 'row' layout, this will cause the row contents to automatically rotate at given interval. This can be used to create a carousel of images.


Expand Container When rendering a list, there are two views in play, one holding each element of the array and the other holding the collection of elements representing the array itself. This refers to the Expand property of the outer container (holding the array).


Aspect Ratio This attribute is useful when rendering a list as grid. The aspect ratio restricts the View to the given aspect ratio.


Html Id The Html Id - it will be reproduced as the id property of the generated HTML tag. This property has no effect for mobile app elements.


Html Class The Html Class - it is reproduced as the class property of the generated Html tag. You can provide multiple class names (space separated). The class name list can include Bulma class names or your custom class names (add corresponding style for the class under APP-STYLE tag. This property has no effect for mobile app elements.
Attributes of the "APP-VIEW" Tag.

PAGE-SCRIPT

"PAGE-SCRIPT" is applicable for web applications only. This is a JavaScript program, that you associate with each page to manage the user interactivity. For mobile apps, dart/flutter code can be associated with each view, because of the nature of its design. For web applications, this is the only place where you can place your code. You can and should have one script for each page in the web application.

A sample script is given below. Your program will mostly listen to system generated events and take action.

$.app.listen('beforeload', 'HOMEPAGE', '', function(data) {
	console.log ('HOMEPAGE LOADING..');
});
$.app.listen('onload', 'HOMEPAGE', '', function(data) {
	console.log ('HOMEPAGE LOADED');
});
$.app.listen('change', 'HOMEPAGE', 'Department', function(data) {
	console.log ('Department Changed');
});
$.app.listen('click', 'HOMEPAGE', 'Department', function(data) {
	console.log ('Department Clicked');
});

Attribute Description
Name The name of the script. Even though there is only one script in the page, you must give a valid name, the system uses this name to access it.


Type This must be set to JavaScript because only JavaScript is supported at this time.


Description Textual description for the purpose of documentation.
Attributes of the "PAGE-SCRIPT" Tag.

PAGE-FLUTTER

"PAGE-FLUTTER" is applicable for mobile apps only. This is a Dart/Flutter program, that you associate with each page to -

  1. Manage the user interactivity. Put this inside the body of a "void init()" function declaration.
  2. Override styling defaults for the page. All methods available for override in APP-FLUTTER are available here.
  3. Optionally, provide implementation of the _buildPage(BuildContext context) method, if you want to take control of rendering the page. This is useful if you want a completely native Flutter page. Remember to check the appropriate box in Tag properties, if you use this feature.

A sample program is given below. Your program will mostly listen to system generated events and take action.

void init() {
	log('PAGE INITIALIZED');
	$.app.listen('click', 'HOMEPAGE', 'TREATMENT-SMALLCARD', (target) {
		UIView view=target as UIView;
		UIData data=view.config['data'] as UIData;
		var sourcedata=data.source;
		$.app.patchAppContext({'treatment': sourcedata});
		$.app.loadPage(this, 'DETAIL-TREATMENT', false);
	});
	$.app.listen('nav', '', 'SAYHELLO', (dynamic target) {
		UIPage page=target as UIPage;
		print('SAYHELLO FIRED');
		$.app.popupPage(page, 'HELLO-POPUP');
	});
}
Color color(String style, {String? elementtype}) => Colors.green;

Attribute Description
Type This must be set to Dart.


Override _buildPage Checkbox, to be checked, if you are providing an alternate implementation of the _buildPage method.


Description Textual description for the purpose of documentation.
Attributes of the "PAGE-FLUTTER" Tag.

APPC-JAVASCRIPT

APPC-JAVASCRIPT is the Web implementation of the Component. The implementation is done by providing an anonymous class. The constructor of the class receives an element object, which provides access to the element properties defined with APP-ELEMENT tag. The class has the following methods in it.

  1. render(clsnames): This method will generate and return HTML string that renders the component.
  2. activate(): This method will be called when the element is activated. You can add interactivity to the element here.
  3. value(newval): This method will be called to set or get the value of the Element. This method should apply the value change, if provided and return the current value inputted by the user.
  4. validate(): This method is called when the page is submitted to validate the user input. It should return the error string or blank if there is no error.
  5. validationError(errorstr): This method is called to display the error to the user. The method should display the error and return the errorstr back.

Example-

class {
	constructor(element) { this.element=element; }
	// Return the HTML string or object {html: string, cls: string, attrs: hash}
	render(clsnames) {
		var data=this.element.config('value') || {};
		var prods=data.ProdItem || [];
		var treats=data.TreatItem || [];
		var ret='<div class="table-container">\n';
		ret+='<table class="table has-sticky-header has-sticky-footer has-sticky-column">\n';
		ret+='<thead><tr>';
		ret+='<th>Name</th>';
		ret+='<th>Quantity</th>';
		ret+='</tr></thead>\n';
		ret+='<tbody>';
		ret+='<tr><th colspan=2>Products</th></tr>';
		for (var i in prods) {
			ret+='<tr>';
			ret+='<th>'+prods[i].ProductName+'</th>';
			ret+='<td>'+prods[i].Quantity+'</td>';
			ret+='</tr>';
		}
		ret+='<tr><th colspan=2>Treatments</th></tr>';
		for (var i in treats) {
			ret+='<tr>';
			ret+='<th>'+treats[i].DiseaseName+'</th>';
			ret+='<td>'+treats[i].Quantity+'</td>';
			ret+='</tr>';
		}
		ret+='</tbody></table></div>';
		return ret;
	}
	// The component is rendered, add interactivity to it
	activate() {
	}
	// Get or Set the value of the component
	value(newval) {
	}
	// Validate the state - return error string or blank for no error
	validate() {
	}
	// Display the error and return it
	validationError(errorstr) {
	}
}

Attribute Description
Type This must be set to JavaScript.
Attributes of the "APPC-JAVASCRIPT" Tag.

APPC-FLUTTER

APPC-FLUTTER is the Mobile implementation of the Component. The implementation is done by providing a Flutter Widget class definition. The class declaration should incorporate "with UIElementMixin" to inherit functions that will allow you to access the element properties.

  1. The Widget constructor will receive two parameters - of type UIPage and String, which should be saved as instance variables in UIElementMixin, as shown in the example below.
  2. Property config of type Map<String,dynamic> inherited from UIElementMixin lets you access the properties defined with APP-ELEMENT.

Example-

// Structure of the Flutter component
class SHOPCART_DTL extends StatefulWidget with UIElementMixin {
	SHOPCART_DTL(UIPage page, String name) { this.page=page; this.name=name; }
	SHOPCART_DTLState createState() => SHOPCART_DTLState(config);
}

class SHOPCART_DTLState extends State<SHOPCART_DTL> {
	Map<String,dynamic> _config;
	SHOPCART_DTLState(this._config);
	@override
	void initState() {
		super.initState();
	}
	@override
	Widget build(BuildContext context) {
		// Build your widget here. The value
		return Text('@TODO SHOPCART_DTL');
	}
}

Attribute Description
Type This must be set to Dart.
Attributes of the "APPC-FLUTTER" Tag.

APPELEMENT-STYLE

"APPELEMENT-STYLE" represents a detailed styling representation that can be applied to an APP-ELEMENT. The styling is generic in nature, and it can be used for both mobile and web apps. This allows you to create styles that can be reused not just across multiple web apps but also between web and mobile apps.

For web applications, additional or as an alternative, custom styling can be provided as CSS with the APP-STYLE node. The CSS however, has no effect on the mobile app rendering.

Attribute Description
Name The name, it is required and is used to refer to the style.


Server Driven

You can designate a specific element style as Server-driven simply by flick of a switch.

For details, see Server-driven UI.



Main Color The main color is the text color for input/display fields and background color for the buttons. This is specified in HTML (#RRGGBBOO) notation (OO is Opacity in Hex) - a helper control is available to select the color. After selecting the color, the opacity value can be typed at the end (Hex). The full color value can also be manually typed.


Complementary Color The specification is same as for Main color and it refers to the background color for text/input fields and text color for buttons.


Label Color The specification is same as for Main color and it refers to the text color of the element label.


Help Color The specification is same as for Main color and it refers to the text color of the element help.


Font Family The font to be used for the main text - use one of the Google font names here


Font Size The size of the font to be used for the main text in pixels.


Bold A boolean value for the main text.


Italic A boolean value for the main text.


Text Shadow A specification for the shadow of the main text. The full specification is a combination of the shadow size, X offset, Y offset and radius.


Description Textual description for the purpose of documentation.
Attributes of the "APPELEMENT-STYLE" Tag.

APPVIEW-FLUTTER

"APPVIEW-FLUTTER" allows you to override the default rendering behavior in the mobile application. The rendering in flutter works in a different way than that way it is done in HTML. For mobile app, each view is converted to a Dart class (which itself extends the Flutter Widget). Typically, you will require custom rendering for the bottommost views in your page. The flutter rendering is quite complex and cannot abstract every nuance of the rendering for you. It is best to use a system generated page layout and then provide custom code for each leaf view in the page.

Before your start writing a customization, spend some time studying the class that the system generates by default. An example is produced below.

class HOMEPAGE$HOME_VIEW extends StatefulWidget {
	String name='HOME-VIEW';
	UIPage page;
	$Null? pdata;
	HOMEPAGE$HOME_VIEW(this.page, $Null? d) { if (d != null) pdata=d; }

	@override
	HOMEPAGE$HOME_VIEWState createState() => HOMEPAGE$HOME_VIEWState(pdata);
}
class HOMEPAGE$HOME_VIEWState extends State<HOMEPAGE$HOME_VIEW> {
	// Source is '', Binding is '';
	$Null? pdata;
	$Null? data;
	InAppWebViewController? webview;
	bool isLoading=true;
	HOMEPAGE$HOME_VIEWState(this.pdata) { _setData(pdata); }
	@override
	void initState() {
		super.initState();
		$.app.listen('rebuild', 'HOMEPAGE', 'HOME-VIEW', (d) { if (mounted) {
			setState(() {});
			rebuildChildren();
			}; });
		$.app.listen('rebuild', 'HOMEPAGE', '', (d) { if (mounted) {
			setState(() {});
			rebuildChildren();
			}; });
	}

	void rebuildChildren() {
		$.app.fire('rebuild', 'HOMEPAGE', 'INFOGRAPHIC', null);
		$.app.fire('rebuild', 'HOMEPAGE', 'HOME-TREATMENTS', null);
		$.app.fire('rebuild', 'HOMEPAGE', 'HOME-PRODUCTS', null);
	}

	Widget _buildWidget($Null? d, BuildContext context) {
		return _defaultWidget(d, context);
	}
	// APP-VIEW - HOME-VIEW
	Widget _defaultWidget($Null? d, BuildContext context) {
		return UIView(widget.page, widget.name)
			.data(data)
			.styleOptions('','black','','')
			.scroll()
			.sizeOptions(0,false)
			.layout('Column')
			.addChild(_childWidget0(d, context))
			.addChild(_childWidget1(d, context))
			.addChild(_childWidget2(d, context))
			;
	}
	Widget _childWidget0($Null? d, BuildContext context) {
		return HOMEPAGE$HOME_VIEW$INFOGRAPHIC(widget.page, null);
	}
	Widget _childWidget1($Null? d, BuildContext context) {
		return HOMEPAGE$HOME_VIEW$HOME_TREATMENTS(widget.page, null);
	}
	Widget _childWidget2($Null? d, BuildContext context) {
		return HOMEPAGE$HOME_VIEW$HOME_PRODUCTS(widget.page, null);
	}
	void _setData($Null? d) { pdata = d; data = pdata; }
	Widget _builder(BuildContext context) {
		return _buildWidget(data, context);
	}
	Widget _builderWithData($Null? d, BuildContext context) {
		_setData(d); return _builder(context);
	}

	@override
	Widget build(BuildContext context) {
		Widget ret = _builder(context);
		return ret;
	}
}

Attribute Description
Override _buildWidget Checkbox, to be checked, if you are providing an alternate implementation of the _buildWidget method.
Attributes of the "APPVIEW-FLUTTER" Tag.

APPVIEW-HTML

"APPVIEW-HTML" allows you to override the default rendering behavior in the Web application. You can provide your own HTML that will be used, and all other nested Views and Elements are ignored. When using custom HTML, the layout value should be set to block and the view must not be a repeating view (bound to array). You would need to add another view under the repeating view, if you want to provide custom HTML for it.

When taking ownership of the view, you need a mechanism to access the data that is bound to the view so it can be included in your custom HTML. This is done using the tag attributes that you put in the custom HTML. data-databind attribute can contain the path of a data element (same syntax as the Data Binding property in the designer) - this tells the system that a data element is bound to the element. data-bindtgt attribute is where you tell where the element value should go -

  1. 'html' means the value would be inserted as the inner HTML of the element,
  2. 'val' means that value of the element is replaced,
  3. Any other value means the attribute with that name is where the value will be inserted. For instance, to bind an image tag to its URL, this should be 'href'.
  4. Examine the default HTML generated by the system (Use your browser's debugging tools for this) as guide in writing the override HTML.

APPVIEW-STYLE

"APPVIEW-STYLE" represents a detailed styling representation that can be applied to an APP-VIEW. The styling is generic in nature, and it can be used for both mobile and web apps. This allows you to create styles that can be reused not just across multiple web apps but also between web and mobile apps.

For web applications, additional or as an alternative, custom styling can be provided as CSS with the APP-STYLE node. The CSS however, has no effect on the mobile app rendering.

Attribute Description
Name The name, it is required and is used to refer to the style.


Server Driven

You can designate a specific view style as Server-driven simply by flick of a switch.

For details, see Server-driven UI.



Height Sometimes it is useful to set the height of a view to a fixed value. You can do it from here.


Background Color This is specified in HTML (#RRGGBBOO) notation (OO is Opacity) and a helper control is available to select the color. After selecting the color you can manually type the Opacity value (in hex) at the end. The entire color value can also be typed.


Background Image You can apply a background image to the view being styled. You must add the image under assets and then select its name here.


Padding The padding is the amount of space to be added inside the area being styled between its edges and the content. A smart input control allows you to input the specification in Uniform, Symmetrical, or Individual formats. Please note that the suffix px, usually used with CSS is not entered and is assumed. Because we are using a generic minimal styling, specifying the values as a percentage is not supported currently.


Margin The margin is the amount of space to be added around the area being styled. The format and restrictions are same as for Padding above.


Border The border is the border specification for the area being styled. The format and restrictions are same as for Padding above.


Border Color The color of the border in HTML (#RRGGBB) notation.


Border Radius You can pick rounded borders for the area being styled. The format and restrictions are same as for Padding above. This setting is only effective if a uniform border (same width for all edges) has been selected. For other formats of border selections, this setting has no effect.


Description Textual description for the purpose of documentation.
Attributes of the "APPVIEW-STYLE" Tag.

APPVIEW-WEBVIEW

Attribute Description
Name The name, it is required.


Target URL The URL of the application to open in the webview. The URL can be external - starting with https:, http:, or data:. Other URL values are assumed to be local web apps and should be declared under APP-ASSETS -> APP-CONTENT.
Attributes of the "PAGE-FLUTTER" Tag.