Display a Custom UI Model from a Web Shell Custom Action

This example continues the Creating a Custom UI Model sample by demonstrating the use of the BBUI.pages.Dialogs object within JavaScript to display a Custom UI Model when an end user clicks an action on a page or a task within a functional area. If you have never written a custom action, be sure to check out Creating the JavaScript for a Simple Custom Action, which describes how to write a custom JavaScript action for Web Shell.

Using the BBUI.pages.Dialogs object is essentially a two-step process: create a function to be called when the form is confirmed, then provide that function to the showCustomForm() method of BBUI.pages.Dialogs.  

Here is the source code for a JavaScript file named MyCustomAction.js.

//use the latest version of jsLint with stricter rule checks
/*lintversion 2*/
 
/*jslint bitwise: true, browser: true, eqeqeq: true, undef: true, white: true, indent: 4*/
/*global BBUI, Ext, $ */
/*JSLint documentation: http://www.jslint.com/lint.html */
 
// Encapsulate all logic inside a self-invoking function so objects are not added to the 
// global (window) object.
(function () {
 'use strict'//enforces latest ECMAScript5
 var ns;
 
 // Ensure the namespace for your action exists.  The naming convention for custom action 
 // namespaces is "BBUI.customactions.yournamespace" where "yournamespace" is the lower-case 
 // type of the UI model project where this file is stored.  For instance, if you are creating
 // a custom action in the Blackbaud.AppFx.Constituent.UIModel project, your action's namespace 
 // would be "BBUI.customactions.constituent".
    ns = BBUI.ns("BBUI.customactions.mytest");
 
 // This is the constructor for the custom action.  The constructor will always be passed a 
 // host object.  See the BBUI documentation for BBUI.pages.ActionHost for information about 
 // properties and methods available on the host object.
    ns.MyCustomAction = function (host) {
 // Cache the host object so it can be referenced by instance methods.
 this.host = host;
    };
 
 // Instance methods are declared as properties of the action's prototype object.
    ns.MyCustomAction.prototype = {
 
 // This method is called when the action is executed.  Since many actions will execute 
 // asynchronously, a callback function is provided as the first parameter.  This callback 
 // function should be called when the action is executed successfully.
        executeAction: function (callback) {
 
 // The function that will be called when the form dialog is confirmed.
 function formConfirmedHandler(args) {
 // The custom action has finished executing.  Call the callback 
 // function so the post-action event can be invoked (if any).
                callback();
            }
 
            BBUI.pages.Dialogs.showCustomForm(this.host.uiModelingSvc, 
 "Blackbaud.CustomFx.MyTest.UIModel.dll", 
 "Blackbaud.CustomFx.MyTest.UIModel.WeatherTest1CustomUIModelMetadataUIModel", 
                {
                    confirmCallback: formConfirmedHandler
                });
 
        }
    };
 
}());

Notice the object literal that is passed in as the last parameter to showCustomForm(). This is the "options" parameter and contains all the optional arguments for showing the form. All methods of BBUI.pages.Dialogs will follow this pattern: the first is the service object required to communicate with the web server (in a Web Shell custom action, this is the host's uiModelingSvc or WebShellSvc property, depending on which dialog is shown), the next parameters are any parameters required to show the dialog, and the last parameter is always an object literal that contains the remaining optional arguments. Which properties the options parameter can have will be outlined in the function's IntelliSense and can also be found by looking at the comments in the BBUI.pages.Dialog source code.

JavaScript Checklist:

Call the Custom Action with a TaskSpec

With the JavaScript complete and deployed to the web server, we can reference it in a TaskSpec. For now, I'm using a task spec that looks like this:

<TaskSpec
	xmlns="bb_appfx_task"
	xmlns:common="bb_appfx_commontypes"
	ID="bc188953-85d3-413f-922a-c3ed65059090"
	Name="Custom Action"
	Description="My custom action task."
	Author="Technical Training"
	FunctionalAreaID="d18fec24-bea9-4212-9abb-18d45804d376"
	Sequence="1"
	DisplayAsAction="true">
	<common:ExecuteCLRAction>
		<common:ScriptIdentifier
		Url="browser/htmlforms/custom/Blackbaud.CustomFx.MyTest.UIModel/MyCustomAction.js"
		ObjectName="BBUI.customactions.mytest.MyCustomAction" />
	</common:ExecuteCLRAction>
</TaskSpec>

Note that this is very similar to how CLR actions are declared, except that instead of a ComponentIdentifier element, I use a ScriptIdentifier element. The ScriptIdentifier element has two properties:

By specifying these two pieces of information, the platform will download the script file, instantiate the custom action object, and call its executeAction() method when a user clicks the action.

After you load the spec, the task should show up in Web Shell as normal and you’ll be ready to test your custom action.

Figure: Within a TaskSpec, custom actions are referenced as a ScriptIndentifier and used to open Custom UI Model dialog forms.

Figure: Custom UI Model dialog screens can be opened using a ScriptIdentifier tag within a TaskSpec.

Conclusion

Just like the ClickOnce Smart Client, Web Shell provides the ability to go above and beyond the Infinity platform's pre-defined action types to create a rich user experience.