Declare Dependencies

2024-03-28

This topic explains how to declare dependencies on script files, libraries, and other resources. For example, when rendering visualizations, the user should explicitly declare the dependency on LabKey.vis to load the necessary libraries.

Declare Module-Scoped Dependencies

To declare dependencies for all the pages in a module, do the following:

First, create a config file named "module.xml" the resources directory:

myModule/resources/module.xml

Then, add <clientDependencies> and <dependency> tags that point to the required resources. These resources will be loaded whenever a page from your module is called. The path attribute is relative to your /web dir or is an absolute http or https URL. See below for referencing libraries, like Ext4, with the path attribute.

<module xmlns="http://labkey.org/moduleProperties/xml/">
<clientDependencies>
<dependency path="Ext4"/>
<dependency path="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" />
<dependency path="extWidgets/IconPanel.css" />
<dependency path="extWidgets/IconPanel.js" />
</clientDependencies>
</module>

Production-mode builds will created a minified JavaScript file that combines the individual JavaScript files in the client library. Servers running in production mode will serve up the minified version of the .js file to reduce page load times.

If you wish to debug browser behavior against the original version of the JavaScript files, you can add the "debugScripts=true" URL parameter to the current page's URL. This will make the server not used the minified version of the resources.

Declare File-Scoped Dependencies

For each HTML file in a file-based module, you can create an XML file with associated metadata. This file can be used to define many attributes, including the set of script dependencies. The XML file allows you to provide an ordered list of script dependencies. These dependencies can include:

  • JS files
  • CSS files
  • libraries
To declare dependencies for HTML views provided by a module, just create a file with the extension '.view.xml' with the same name as your view HTML file. For example, if your view is called 'Overview.html', then you would create a file called 'Overview.view.xml'. An example folder structure of the module might be:

myModule/
queries/
reports/
views/
Overview.html
Overview.view.xml
web/

The example XML file below illustrates loading a library (Ext4), a single script (Utils.js) and a single CSS file (stylesheet.css):

<view xmlns="http://labkey.org/data/xml/view">
<dependencies>
<dependency path="Ext4"/>
<dependency path="/myModule/Utils.js"/>
<dependency path="/myModule/stylesheet.css"/>
</dependencies>
</view>

Within the <dependencies> tag, you can list any number of scripts to be loaded. These should be the path to the file, as you might have used previously in LABKEY.requiresScript() or LABKEY.requiresCss(). The example above includes a JS file and a CSS file. These scripts will be loaded in the order listed in this file, so be aware of this if one script depends on another.

In addition to scripts, libraries can be loaded. A library is a collection of scripts. In the example above, the Ext4 library is listed as a dependency. Supported libraries include:

  • Ext3: Will load the Ext3 library and dependencies. Comparable to LABKEY.requiresExt3()
  • Ext4: Will load the Ext4 library and dependencies. Comparable to LABKEY.requiresExt4Sandbox()
  • clientapi: Will load the LABKEY Client API. Comparable to LABKEY.requiresClientAPI()
Declaring dependencies in a .view.xml file is the preferred method of declaring script dependencies where possible. The advantage of declaring dependencies in this manner is that the server will automatically write <script> tags to load these scripts when the HTML view is rendered. This can reduce timing problems that can occur from a dependency not loading completely before your script is processed.

An alternative method described below is intended for legacy code and special circumstances where the .view.xml method is unavailable.

Using LABKEY.requiresScript()

From javascript on an HTML view or wiki page, you can load scripts using LABKEY.requiresScript() or LABKEY.requiresCss(). Each of these helpers accepts the path to your script or CSS resource. In addition to the helpers to load single scripts, LabKey provides several helpers to load entire libraries:

<script type="text/javascript">
// Require that ExtJS 4 be loaded
LABKEY.requiresExt4Sandbox(function() {

// List any JavaScript files here
var javaScriptFiles = ["/myModule/Utils.js"];

LABKEY.requiresCss("/myModule/stylesheet.css");
LABKEY.requiresScript(javaScriptFiles, function() {
// Called back when all the scripts are loaded onto the page
alert("Ready to go!");
});
});

// This is equivalent to what is above
LABKEY.requiresScript(["Ext4", "myModule/stylesheet.css", "myModule/Utils.js"], function() {
// Called back when all the scripts are loaded onto the page
alert("Ready to go!");
});
</script>

Loading Visualization Libraries

To properly render charts and other visualizations, explicitly declare the LABKEY.vis dependency. Using the example of a script with "timeChartHelper.js", the declaration would look like:

// Load the script dependencies for charts. 
LABKEY.requiresScript('/vis/timeChart/timeChartHelper.js',
function(){LABKEY.vis.TimeChartHelper.loadVisDependencies(dependencyCallback);});

Create Custom Client Libraries

If you find that many of your views and reports depend on the same set of javascript or css files, it may be appropriate to create a library of those files so they can be referred to as a group. To create a custom library named "mymodule/mylib", create a new file "mylib.lib.xml" in the web/mymodule directory in your module's resources directory. Just like dependencies listed in views, the library can refer to web resources and other libraries:

<libraries xmlns="http://labkey.org/clientLibrary/xml/">
<library>
<script path="/mymodule/Utils.js"/>
<script path="/mymodule/stylesheet.css"/>
</library>
<dependencies>
<dependency path="Ext4"/>
<dependency path="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"/>
</dependencies>
</libraries>

Note that external dependencies (i.e. https://.../someScript.js) can only be declared as a dependency of the library, and not as a defining script.

Troubleshooting: Dependencies on Ext3

Past implementations of LabKey Server relied heavily on Ext3, and therefore loaded the ExtJS v3 client API on each page by default. This resulted in the ability to define views, pages, and scripts without explicitly declaring client dependencies. Beginning with version LabKey Server v16.2, DataRegion.js is no longer dependent on ext3, so it is no longer loaded and these views may break at run time.

Symptoms: Either a view will fail to operate properly, or a test or script will fail with a JavaScript alert about an undefined function (e.g. "LABKEY.ext.someFn").

Workaround: Isolate and temporarily work around this issue by forcing the inclusion of ext3 on every page. Note that this override is global and not an ideal long term solution.

  • Open (Admin) > Site > Admin Console.
  • Under Configuration, click Site Settings.
  • Check one or both boxes to "Require ExtJS v3… be loaded on each page."

Solutions:

Correct views and other objects to explicitly declare their dependencies on client-side resources as described above, or use one of the following overrides:

Override getClientDependencies()

For views that extend HttpView, you can override getClientDependencies() as shown in this example from QueryView.java:

@NotNull
@Override
public LinkedHashSet<ClientDependency> getClientDependencies()
{
LinkedHashSet<ClientDependency> resources = new LinkedHashSet<>();
if (!DataRegion.useExperimentalDataRegion())
resources.add(ClientDependency.fromPath("clientapi/ext3"));
resources.addAll(super.getClientDependencies());
.
.
.

Override in .jsp views

Note the <%! syntax when declaring an override as shown in this example from core/project/projects.jsp.

<%!
public void addClientDependencies(ClientDependencies dependencies)
{
dependencies.add("Ext4ClientApi");
dependencies.add("/extWidgets/IconPanel.js");
dependencies.add("extWidgets/IconPanel.css");
}
%>

Related Topics