App context
An overview of the functionality provided by the global application context.
Overview
Along with all of the important classes and types that make up the Desk framework, the main package also provides the app object, which is a singleton instance of the GlobalContext class. This object has two main roles:
- It serves as the root of the application hierarchy, and references several other context objects that affect the application as a whole, such as activities and services.
- It provides commonly used functionality that controls the overall application, e.g. navigation, page and modal rendering, and logging.
The app
object is created immediately, and is made available as a top-level import from the main Desk package.
- appThe current instance of the global application context.
- class GlobalContextA singleton class that represents the global application state.
Initializing the global app context
The functionality provided by the application context depends on the runtime platform in which your app is used, and needs to be initialized before use.
- To initialize the app context in a browser (i.e. using the DOM API) you’ll need to use the useWebContext function.
- To initialize a test with full app functionality (activities, rendering, etc.) you’ll need to use the useTestContext function.
- Currently, no other platforms are supported — but with more platforms, each package would have to export an initialization function to set up its own context objects.
The use..Context
functions take an options
argument, which may either be an instance of the particular context’s options class, or a function. The function is called with a default options object, which can be modified to customize the context. The ConfigOptions base class of the options object is available for use elsewhere in your code, e.g. to configure a service (refer to examples below).
- class ConfigOptions abstractA base class for options objects that can be passed to a constructor or factory function.
After initialization, you can add activities and (optionally) services to the application hierarchy, and customize several other app elements; refer to each of the sections below.
Initializing activities
To use activities effectively, they need to be added to the application hierarchy. Use the following method to add an activity directly to the app context.
- addActivity(activity, activate?)Adds an activity to the global application context.
This method adds the provided activity to the activity context, available as app.activities. This object contains a list of activities, as well as a reference to the navigation controller that handles platform-dependent logic for external navigation (see below).
For more information, refer to the documentation for activities.
Initializing services
The app context also includes a method to register a service, so that it can be retrieved (or observed) by name — making it available to the rest of the application.
- addService(service)Adds a service to the global application context.
This method adds the provided service to the service context, available as app.services. This object manages the list of currently registered services.
For more information, refer to the documentation for services.
// you can chain method calls together:
useWebContext((options) => {
// ... set up the app context using options
})
.addService(new MyService())
.addActivity(new MainActivity(), true);
Using global app navigation
Desk applications use a global navigation context, like a single-page web application that runs in a browser — even if the app is not running in a browser (e.g. while testing, or in a native runtime environment).
The navigation controller encapsulates a simplified version of the browser’s history API, with methods that can be called to navigate between paths, and to go back within the navigation history. Synchronous (non-blocking) versions of these methods are also available on the global app
object.
- navigate(target, mode?)Navigates to the specified path asynchronously.
- goBack()Navigates back to the previous location in the location history stack.
The navigation controller itself is available as app.activities.navigationController, and is overridden automatically depending on the runtime platform (e.g. the browser DOM) with a specific subclass of the NavigationController class.
- class NavigationControllerAn object that encapsulates the current location within the application navigation stack, part of the global application context.
Rendering views
While the app is running, the app
object is used to render the application’s UI. Most commonly, an activity will render its view when ready (i.e. from the Activity.ready() method), using one of the methods below.
- showPage(view?)Displays a full-screen page with the specified content view.
- showDialog(view?)Displays a modal dialog with the specified content view.
class MyActivity extends Activity {
// ...
ready() {
this.view = new MyView();
app.showPage(this.view);
}
}
Predefined modals
The app context also includes methods to render predefined modal views, which can be used at any time — usually from event handlers within an activity. The alert and confirmation dialogs, as well as modal menus that are displayed, may be rendered using platform-specific UI elements or using a custom view. The app.theme object includes options for customizing the appearance of these views.
- showAlertDialogAsync(config, buttonLabel?)Displays an alert dialog with the specified content and a single dismiss button.
- showConfirmDialogAsync(config, confirmLabel?, cancelLabel?)Displays a confirmation dialog with the specified text and buttons.
- showModalMenuAsync(config, ref?)Displays a context/dropdown menu with the provided list of items.
// simple usage example:
app.showAlertDialogAsync("An error occurred");
// with options and i18n:
const errorDialog = new MessageDialogOptions(
[
strf("An error occurred: %[message]"),
strf("The data could not be saved, please try again."),
],
strf("Try again"),
strf("Cancel"),
strf("Show details"),
);
app.showAlertDialogAsync(errorDialog.format(err));
Note: While these methods can be used from anywhere in the application, they’re typically only used from within an activity. Using these rendering methods from within services or models, for example to show error messages or perform data validation, is considered an anti-pattern and should be avoided.
Custom rendering
To render a view in any other way, e.g. as a modal anywhere else on screen, you can use the following method.
- render(view, place)Renders the provided view using specified placement options.
All of the show
and render
methods leave the heavy lifting to the platform-specific rendering context, which is referenced as app.renderer. This object is initialized automatically, as an instance of the following class.
- class RenderContext abstractAn abstract class that supports global view rendering, part of the global application context.
Animations
UI elements can be animated using the following method. There are also several other ways to introduce animation into your application — for more information, refer to the documentation for animations.
- animateAsync(ref, animation?)Runs an animation on the provided view output element.
Customizing app behavior and styles
The app context refers to two other objects that are used to customize the application as a whole.
The theme object is used to customize the appearance of the application. For more information, refer to the documentation for Themes and colors and icons.
Another important aspect of UI presentation beyond its appearance is text handling for internationalization (i18n). The i18n property refers to the current I18nProvider instance, which is used to translate and format strings automatically. For more information, refer to the documentation for internationalization.
- i18nThe current internationalization context, an object that implements I18nProvider.
Registering log and error handlers
The app context includes functionality for sending log messages and errors to registered handlers. This functionality is provided by the app.log methods. By default, messages are sent to the console, but you can register a custom handler to send messages to a different destination such as a file or a remote server.
Use the following methods to register a custom log handler and/or error handler.
- addLogHandler(minLevel, f)Adds a log sink for the current LogWriter instance.
- setErrorHandler(f)Sets a global unhandled error handler.
For more information, refer to the documentation for errors and logging.
Other functionality
In addition to the methods and properties described above, the app context provides several other commonly used ‘global’ objects and methods. Refer to the documentation for each of these objects for more information.
- schedulerThe global asynchronous task scheduler, an instance of Scheduler.
- logThe global message log writer instance, an instance of LogWriter.
- class GlobalEmitterAn object that’s used for emitting events.