Recently in Form Guides Category

The delivery of Guides (formally form guides) in LiveCycle ES2 has changed significantly.  Previously, form guides were rendered from an XDP using the Forms API.  Now that Guides in LiveCycle ES2 are derived from a model however the Forms API does not have to be used.  Instead, services have been made available that make it very easy to create a LiveCycle process that will return a guide.  When using LiveCycle Workspace this work is handled automatically but there will be situations where a developer will want to display a guide as part of their own web application.  In these cases LiveCycle provides several methods to invoke a process.  A simple REST URL or web service call could be made or the invocation API could be accessed programmatically.

In order to show how you can programmatically display a guide in a web application I have posted a recipe to the new LiveCycle Cookbook that is part of the Adobe Developer Connection.  Check it out and let me know what you think!  Also, I plan to start adding more LiveCycle and Guide recipes to the cookbook.  If you have any suggestions for content feel free to pass them along.

View all my cookbook recipes here.

LiveCycle ES Designer makes it easy to set up a connection to a WSDL in order to execute some web service call.  This functionality can also be extended to your form guide with a few simple steps.

A data connection to a web service will first need to be defined on your form.  These steps are the same regardless of what your ultimate form rendering will be.

  • Create your data connection in LiveCycle Designer.
  • Set up required data bindings.
  • Add the web service invoke button to your form.

At this point if you were to preview your form and click the invoke button a client-side web service call would be invoked by the PDF based on your data bindings.  A form guide however must execute its web service calls on the server which means a few extra steps are required.

Now let's make the required changes to have this web service executed by a form guide.

  • Change the execution options of the invoke button to Run At Server.  If you also want the PDF to execute web service calls on the client you will need to add two invoke buttons and hide the one that will be used by the form guide.

As a minimum this is all that needs to be done.  Adding this button you your form guide will allow it to execute the desired web service and display the result based on your data bindings.  I am now going to dig a little deeper however to see how we can improve the experience on the form guide.

  • Add a hidden field to hold the status of asynchronous calls (eg. asyncCallActive).  This field will indicate to the guide if a server-side web service call is currently active.
  • Add another hidden button (eg. executeWS) whose click event is set to run at server.
  • Add the following script to the button's click event (invokeBtn is the name of your web service execute button).
invokeBtn.execEvent("click");
asyncCallActive.rawValue = "false";

At this point we have all the server-side pieces in place for the form guide to be able to execute a web service.  All that still needs to be done is add the ability on the client to actually invoke this web service.  This step for the most part depends on your particular form design.  Typical usage includes invoking the web service on exit of some field or just by clicking a button.  Let's look at the on exit case.

Let's assume we have a web service that looks up the weather for a given zip code.  In this case it would make sense to invoke the web service on the exit event of a zip code field.

  • Add the following client-side script to the field's exit event.
asyncCallActive.rawValue = "true";
executeWS.execEvent("click");

In the form guide whenever this field is executed the click event of the executeWS button will be executed on the server.  The result of the web service call will be merged back into the form guide based on what ever field bindings you had defined.

We're almost done but not quite. You may have noticed that I have been setting the rawValue of the asyncCallActive field but not doing anything with it.  Add the following client-side script to this field's change event.

if (xfa.host.name == "Flash" && this.rawValue)
{

    import mx.managers.CursorManager; 
if (this.rawValue == "true")
CursorManager.setBusyCursor();
else
CursorManager.removeBusyCursor();
}

This script is a form guide trick that allows you to add ActionScript to your form that will only be executed in the form guide.  The check that xfa.host.name is Flash ensures this script will not execute on the PDF.  As a result we are able to set the Flex busy cursor state based on the value of the asyncCallActive field.  This helps your form provide feedback to the user that some back-end processing is being done.

Download XDP

When designing forms in LiveCycle Designer ES that will eventually be rendered as a form guide by the server I regularly come across the need for script on the form to notify the form guide something needs to be done.  One such case is the use of xfa.host.messageBox().  When this script is executed in a form guide the default Flex Alert is shown.  While this is fine for quick informational messages it cannot be styled to match the look of my form guide nor can it handle any user response.  This article covers one possible technique that can be used to allow your form scripting to send events to the form guide.

 

Step 1: xfa.host.name == "Flash"

This one line of script will very quickly become your friend when scripting a form that may be rendered as a form guide.  Keying on the current host name allows you to target your script to only run in certain environments.  This technique is not only valuable to ensure scripting outside of the supported xfa subset can still be executed in Acrobat/Reader it also opens the door for some inventive scripting when the form is being hosted in Flash (ie. form guide).  One such door that opens is the ability to enter ActionScript directly in your form design script that will only get executed when in a form guide context.

 

Step 2: Add ActionScript to your form design script

Let's look at a case where the client-side click event of a button in your form design has the following script.

//Show Yes/No message box
var ans = xfa.host.messageBox("My Text" , "My Title",  2);
    
if (ans == 3) 
{
   // No is selected
}
else
{
   // Yes is selected
}

In order to get a similar result in the form guide where the user gets presented with a Yes/No message box that must be answered an event can be fired. On the same click event we can add the following script.

if (xfa.host.name == "Flash")
{
    this.dispatchEvent(new XfaModelEvent("showCustomDialog", false, false, "My title", "My text", null);
}

This ActionScript will fire an event on the form guide that can be listened for and acted upon accordingly.  The name of the event, showCustomDialog, could be any string you wish.  You could also fire events with multiple names fro myour form script for any number of desired behaviours.

Step 3: Create a Popup Manager in Flex

In order for this technique to work your form guide will need to reference a custom Flex library that includes a custom guide layout (ie. Wrapper).

First, I'll explore the creation of a Xfa Popup Manager in Flex. There are many ways you could write your Flex code to display popups requested from scripting in your form design.  This method is one such approach but could be altered to suit your individual needs.  Here are the basic steps I will be following.

  1. Create a class called XfaPopUpManager
  2. Create a static public function called "manage" that takes a Page as input
  3. Set up listeners for all panel items on the current page
  4. Handle popup events when they occur
  5. Listen for popup close events

And here is the abbreviated class code.

public class XfaPopUpManager
{
    private var popup:Alert;        
        
    static public function manage (oPage:Page):XfaPopUpManager
    {
        return new XfaPopUpManager(oPage);
    }
        
    public function XfaPopUpManager(oPage:Page):void
    {
        addPopupListeners(oPage);            
    }        
       
     /**
      * Creates listeners in order to provide a custom popup dialog for
      * those fields that dispatch a "showCustomDialog" XfaModelEvent at runtime.
      */
     public function addPopupListeners(oPage:Page):void
     {
         for each (var item:PanelItem in oPage.layout.getPanelItems()) 
         {
             if(item.boundData != null && item.boundData.hasEventListener("showCustomDialog") == false)
             {
                  item.boundData.addEventListener("showCustomDialog", popupHandler);
              }
          }
     }




    /**    
* show popup has been requested - present a dialog.
*/
protected function popupHandler(oEvent:Event):void
{
if (displayPanelItems[oEvent.currentTarget] != null)
{
var title:String = "";
var msg:String = "";
if (oEvent is XfaModelEvent)
{
title = XfaModelEvent(oEvent).propertyName;
msg = XfaModelEvent(oEvent).propertyValue;
}
doShowPopup(title, msg);
}
}

    /** 
* Creates Dialog style popup for programmed popUp requests.
* @param title
* @param displayText
* /
protected function doShowPopup(title:String, displayText:String):void
{
// Prevent multiple occurrences of a modal dialog. This may happen due to cloned
// fields that already have listeners.
if (popup != null) return;
var flags:uint = Alert.YES | Alert.NO;
popup = Alert.show(displayExt, title, flags, null, handlePopupClose);
}

    /** 
* Handle the pop up close event
*/

private function handlePopupClose(event:CloseEvent):void
{
if (event.detail == Alert.YES)
{
//Yes selected
} else if (event.detail == alert.NO)
{
//No selected
}
popup = null;
}
}

 

In the handlePopupClose function you could place any logic required by the form. An extension to this technique that I won't cover here would be to pass the SOM expression of a hidden button on your form that could be programmatically clicked as another parameter of the XfaModelEvent.  This way the script that runs after the message box is dismissed could be the same whether the form is being hosted by Acrobat or Flash.

For example...

Xfa.instance.resolveNode(somExpression).execEvent("click");

 

Step 3: Hook it all up  in your custom guide layout

We're almost done!  All that needs to be done now is some wiring in your custom guide layout.

First you will need to listen for the Page Selection Change event.

panelManager.addEventListener(GAEvent.PAGE_SELECTION_CHANGE, pageChange);

This listener can be added to your wrapper's createChildren() function.

Next the page change listener function needs to be created which is where the popup manager we created will be set up.

private function pageChange(event:GAEvent):void 
{
    //...
    XfaPopUpManager.manage(event.page);
    //...
}

When running a a form guide your form should now be able to dispatch events to the guide runtime and then act on those events based on the custom Flex code you tied those events to.

When creating custom layouts to be used with form guides it is a good practice to ensure that your layouts can be styled.  One method that will achieve this goal is to use the style names that get defined by Guide Builder.  By adding these style names to various components in your layout you can take advantage of all the styling that gets defined in Guide Builder and is included with each guide definition.

Here are a selection of style names that can be added to your custom guide layouts.  These styles can be defined by going to Customize Appearance in Guide Builder and navigating to the appropriate panel listed under each style name description.

Style Name MXML Description
application

<mx:VBox width="100%" height="100%" styleName="application"/>

Defines the overall background gradient colors for the guide.

Guide Builder: Customize guide, logo and progress bar -> Background
logo <mx:VBox styleName="logo" left="0"/> Specifies a location to hold an image such as a logo.

Guide Builder: Customize guide, logo and progress bar -> Logo
guidetitle <mx:Label text="{panelManager.gaModel.name}" styleName="guidetitle"/> Specifies font and color styles.

Guide Builder: Customize guide, logo and progress bar -> Font
guide

<mx:HDividedBox styleName="guide"/>

Defines background color/image, border color, padding and corner radius styles.

Guide Builder: Guide Builder: Customize guide, logo and progress bar -> Border, Guide background
panelnav

<mx:Panel styleName="panelnav"/>

Defines font, background color, background image, background alpha, border and header styles.

Guide Builder: Customize panels -> Panel border, Panel header, Navigation, Font
guidehelp

<mx:Panel styleName="guidehelp"/>

Defines font, background color, background image, background alpha, border and header styles.

Guide Builder: Customize panels -> Panel border, Panel header, Guide help, Font
paneldata

<mx:Panel styleName="paneldata"/>

Defines font, background color, background image, background alpha, border and header styles.

Guide Builder: Customize panels -> Panel border, Panel header, Data entry, Font
buttons

<gc:NextPanelButton styleName="buttons"/>

Defines theme color, fill colors and font styles.

Guide Builder: Customize buttons and repeater layouts -> Button color, Button theme color, Font

 

For further information on how to include form guide specific style names in your own layouts browse the guide source included with the LiveCycle install.  The source and associated Flex project have been made available for all the default guide layouts, panel layouts and guide controls.

./LiveCycle8.2/LiveCycle_ES_SDK/samples/FormGuides/GuideSource

In my next post I will cover the various styles that can be applied to your custom panel layouts.

A great new blog is now available from the Form Guide team at Adobe.  This blog will contain contributions from many memebers of the form guide team as they discuss tips, tricks and best practices concerning Form Guides.

The team is also looking for questions and suggestions from those early adoptors out there already using Form Guides to help guide future postings so be sure to provide lots of comments.

The URL for the new blog is:

http://blogs.adobe.com/lcformguides/





technorati tags:

Blogged with Flock

About Me

Anthony Rumsey
I am a Computer Scientist at Adobe Systems in Ottawa, Canada. Currently occupying my time developing enterprise applications using a combination of the next generation of Flex and LiveCycle.

The views expressed in this blog are my own and do not necessarily reflect the views of Adobe Systems Incorporated.

About this Archive

This page is an archive of recent entries in the Form Guides category.

Flex is the previous category.

General is the next category.

Find recent content on the main index or look in the archives to find all content.