Visual Workflow is a powerful Business Process Management tool built into the Force.com platform. But currently the are limits to what you can do with your flow UI. One such limit is the lack of ability to set a field focus (the active field when the page finishes rendering). When this came up in conversation recently, it got me thinking, Maybe there is a way.

Standard Visual Workflow

If you use the default flow launcher, you are brought to a standard UI that all flows use.

Basic Flow viewer. Simple and effective.

Putting your flow in Visualforce

But I’ve always preferred the option of nesting my flow in a Visualforce page. I find this to be a cleaner, more flexible display. Furthermore, once you have your flow sitting inside the VF container, you now have an HTML page where you can place your own custom code.

Some of you already get where I’m going with this, I suspect.

If you’re not familiar with using flows in Visuaforce, it couldn’t be easier and is well documented in the Visualforce Developer guide. In my page, I use flow:interview tag and set the name attribute to the the Unique Name value of my flow. I was using a flow called New_Account_Contact_Opportunity. Here is my Visualforce markup:

<apex:page tabStyle="Job_Application__c" >
 <flow:interview name="New_Account_Contact_Opportunity" ></flow:interview>
</apex:page>

Flow in VF uses the Salesforce tab style and sets focus on first text field

Putting the flow into a Visualforce page means that I can use the standard Salesforce tab styles. And interestingly, it does put the focus on the first field. But only on the first text field. So to put the focus where I wanted, I needed to do some more work.

A first quick and dirty effort revealed that using the inspector to find the element ID of the field and setting the focus in a simple script would work:

<script>
    document.getElementById('j_id0:j_id1:i:f:pb:d:Job_App_Position.input').focus();
</script>

But I had a problem!

Handling Visualforce Element ID Decoration

All of the gobbledeegook at the front of my element ID will be familiar to those of you who have delved into the innards of a Visualforce page. All that “j_id0” stuff can change if you modify your page. Additionally, because the flow element in my page is completely monolithic, I’m unable to create my own visualforce element ID to reference using the $Component global variable.

My mind came back to a little helper function I had encountered before, so I decided to give it a try. Using that function, with a little bit of additional code, here’s what I ended up with:

<apex:page tabStyle="Opportunity" >
    <flow:interview name="New_Account_Contact_Opportunity" ></flow:interview>
    <script>
        setFocus();
        function getApexElementByID(tagname, eid) {
            var tags = document.getElementsByTagName(tagname); //get a bunch of tags. 
            var regex = new RegExp(":" + eid + "$");
            for (var i=0; i < tags.length; i++) {
                if (tags[i].getAttribute("id") != null) {
                    var idVal = tags[i].getAttribute("id");
                    var pos = idVal.search(regex);
                    if (pos != -1) return tags[i];
                }
            }
            return null;
        }
        function setFocus() {
            var focusTag = getApexElementByID("input","Account_Name\.input")
            if (focusTag){ 
                focusTag.focus();
            }
        }
</script>
</apex:page>

I wish I knew the name of the originator of this getApexElementByID function. I discovered it in a page I inherited from a training project and I can’t take credit for it. If I knew who it was, I would buy that developer a beer. It’s a simple way to get a specific tag from a Visualforce page based on the automatic element ID decoration. If you decide to use it, make sure you call it with the correct tag type. Also make sure you escape out any regex special characters. For instance, if you want picklist called Opportunity_Stage_Name.input, you’ll need to call it like this:

var focusTag =  getApexElementByID("select","Opportunity_Stage_Name\.input");

However this left me with another problem.

Flows Have Many Pages

The Visualforce page is the same throughout the flow. But fields on the UI change each time my flow goes to a new step. Which means I’ll have a focus for one field on one screen, but for the other however many steps of my flow, I’ll need to add some more logic to my setFocus function. For my sample flow, with two pages, I ended up with this:

<apex:page tabStyle="Opportunity" >
    <flow:interview name="New_Account_Contact_Opportunity" ></flow:interview>
    <script>
        setFocus();
        function getApexElementByID(tagname, eid) {
            ...
        }
        function setFocus() {
            var focusTag;
            if (focusTag = getApexElementByID("input","Account_Name\.input")){ 
                //first page focus
                focusTag.focus();
            } else if(focusTag = getApexElementByID("input",
                             "Opportunity_Stage\.Opportunity_Prospecting\.radio")){          
                //second page focus
                focusTag.focus(); 
            } 
        } 
    </script> 
</apex:page>

Taking It Further

Now without a doubt, there are ways you could go well beyond my initial fiddling with this. Some thoughts that come to mind:

  • jQuery. Of course, the amount of code I would need to write if I simply use jQuery would be reduced massively. 
  • Pass the field names to the page using a url parameter list so that I wasn’t hard coding the fields on my page.
  • Create a custom setting that stored the names of the fields to use as focus fields for each page.

Hopefully this inspires some folks to go out and begin to play with your flow UI. If you want to use my examples, you can use the pages and flow from this github repo. You can also install an unmanaged package with flow examples and Apex connectors if you want to explore Visual Workflow even further with the Getting Started Pack.

And if you’re asking yourself, “why can’t you just set the field focus with Visual Workflow?” It is a good question. There are many reasons why features do or don’t make it into a particular release of Salesforce.com and honestly, I’m not in a position to say why. But I’m sure the person who conceived this idea on Idea Exchange would be eternally grateful if you voted up their idea.

And finally…

Thanks to Patrick who was taking Andrew’s DEV401 training class this week whose question inspired this blog post.

Happy coding! And happy flowing!

 

tagged , , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Raymond Gao

    It would be nice to have some kinds of Javascript MVC framework to deal with this, i.e. Backbone.JS, Angular.JS, … Otherwise, you have lots of fragmented code, which becomes hard to manage in large projects.

    http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/

    • Peter Chittum

      I wholeheartedly agree that for anything more than a simple basic tweak like this, you would want something that would scale much better than what I did.

      This blog was to inspire people to look into new ways to work with the UI of flows. If you come up with something that takes these ideas and applies one of the frameworks you speak of, I’d be most interested. Please tweet me if you do @pchittum.

      Great framework comparison page, by the way.

  • Emilio Bernabei

    This is a big help, thanks. I’ve embedded flows into my HTML5 lean visual management solution (leankor) and was wondering how to set focus. I place flows in pop-ups actually… which makes for extra “fun” :-)

    • Peter Chittum

      You’re welcome. I’m glad it was a help.

  • Patrick Divine

    Hi Peter, this is Patrick. Thank you so much for your help on this. It works perfectly.

    I have two more hurdles to pass on the project I’m working on. I was hoping you could point me in the right direction. The next challenge is to have the enter key “click” the next button when pressed.

    Once again, thank you so much for your help Peter,
    Patrick

    • Peter Chittum

      Hi Patrick, sorry I never got back to you.

      I’ve read some articles on how to detect key presses on pages using Javascript, but this is never assured.

      The automatically click when enter button is pressed requirement is altogether more difficult for a number of reasons. But if you can get it to work, it will be with a similar mechanism: using Javascript, or more likely jQuery in this instance to help you capture the user’s keypress and then respond to it.

      Good luck.

      • Patrick Divine

        Excellent. Thank you Peter. This is much appreciated,

        Patrick

  • Phillip Southern

    Nice post….great breakdown of examples…always interesting to see how much further we can interact with flow.